Flutter 开发的极简风格聊天界面

总结

  • 花时间重构了之前写的聊天程序的页面。
  • 使用最新的Flutter Sdk 重写。
  • 优化了高斯模糊的写法。
  • 优化了对安全区域的判断逻辑。
  • 增加文字和图片的发送效果。
  • 增加图片查看功能。

项目中使用到的一些第三方组件

yaml 复制代码
get: ^4.7.3

# 系统接口
device_info_plus: ^12.2.0           # 设备信息(全平台支持)
permission_handler: ^12.0.1         # 权限处理(不支持PC - MacOS)

# 图像渲染
flutter_svg: ^2.2.3
extended_image: ^10.0.1             # 图片展示

# 数据存储
xml: ^6.6.1                         # xml解析 - 解析表情包文件
shared_preferences: ^2.5.4

# UI交互
easy_refresh: ^3.4.0                # 下拉刷新
flutter_slidable: ^4.0.3            # 滑动删除
flutter_smart_dialog: ^4.9.8+9      # 消息弹窗
flutter_keyboard_visibility: ^6.0.0 # 键盘状态监听
chat_bottom_container: ^0.4.0       # 输入框切换动画组件

# 本地资源选择
wechat_assets_picker: ^10.0.0       # 图片\视频选择器(不支持PC)
wechat_camera_picker: ^4.4.0        # 图片\视频拍摄器(不支持PC)

关于IOS上的一些权限配置

Podfile 文件

js 复制代码
post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
      target.build_configurations.each do |config|
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
      '$(inherited)',
      'PERMISSION_CAMERA=1',
      'PERMISSION_PHOTOS=1',
      'PERMISSION_MICROPHONE=1',
      ]
    end
  end
end

Info.plist 中增加对权限的描述

xml 复制代码
	<key>NSCameraUsageDescription</key>
	<string>xxx</string>
	<key>NSAppleMusicUsageDescription</key>
	<string>xxx</string>
	<key>NSMicrophoneUsageDescription</key>
	<string>xxx</string>
	<key>NSPhotoLibraryAddUsageDescription</key>
	<string>xxx</string>
	<key>NSPhotoLibraryUsageDescription</key>
  <string>xxx</string>

自定义滚动透明化的Appbar标题

dart 复制代码
/// 滚动动画的App标题
mixin AppBarMixin on GetxController {
  /// 控制Appbar标题透明度的控制器
  AnimationController? fadeController;

  /// 透明度动画参数
  late Animation<double> fadeAnimation;

  /// 滚动列表的控制器
  final ScrollController scrollController = ScrollController();

  /// 初始化
  void onInitAnimation(GetSingleTickerProviderStateMixin item) {
    fadeController = AnimationController(
      duration: Duration(milliseconds: 300),
      vsync: item,
    );
    fadeAnimation = Tween<double>(begin: 0, end: 1).animate(fadeController!);

    scrollController.addListener(() {
      if (scrollController.offset >= 50) {
        //titleOpacity.value = 1;
        fadeController?.forward();
      } else {
        if (fadeAnimation.value != 0 && scrollController.offset > 0) {
          var fade = scrollController.offset / 50;
          fadeController?.animateTo(fade);
        } else {
          //titleOpacity.value = 0;
          fadeController?.reverse();
        }
      }
    });
  }

  @override
  void onClose() {
    fadeController?.dispose();
    scrollController.dispose();
    super.onClose();
  }
}

Hero动画

动画的Key需要传递到第二个页面。

dart 复制代码
Get.to(
       () => PreviewImagePage(),
        transition: Transition.noTransition,
        arguments: {
       "hero": message.heroKey,
       "source": imageMessage.image,
  },
);

 /// Hero 动画 Key
String heroKey = Get.arguments['hero'];

Hero(
   tag: heroKey,
   child: widget,
),

输入框切换动画

dart 复制代码
使用的第三方组件
chat_bottom_container: ^0.4.0       # 输入框切换动画组件

消息定义

dart 复制代码
import 'dart:math';

/// 消息基类
abstract class Message {
  final String name;
  final String avatar;
  final bool self;

  final String id = Random().nextInt(100000000).toString();

  /// 正在发送
  final bool sending = false;

  /// 发送失败
  final bool failed = false;

  /// 是否群聊
  final bool isGroup = false;

  abstract final bool center;
  abstract final bool canClick;
  abstract final MessageKind kind;

  Message({
    required this.avatar,
    required this.name,
    required this.self,
  });
}

enum MessageKind {
  unkonw,
  text,
  image,
  video,
}

/// 文本消息
class TextMessage extends Message {
  final String text;

  TextMessage({
    required this.text,
    required super.avatar,
    required super.name,
    required super.self,
  });

  @override
  bool get center => false;

  @override
  bool get canClick => false;

  @override
  MessageKind get kind => MessageKind.text;
}

/// 图片消息
class ImageMessage extends Message {
  final String image;
  final double w;
  final double h;

  ImageMessage({
    required this.image,
    required super.avatar,
    required super.name,
    required super.self,
    required this.w,
    required this.h,
  });

  /// 跳转的页动画Key
  String get heroKey => "PreviewImage-$id";

  @override
  bool get center => false;

  @override
  bool get canClick => true;

  @override
  MessageKind get kind => MessageKind.image;
}
相关推荐
韩曙亮1 小时前
【Flutter】Flutter 进程保活 ③ ( 屏幕常亮设置 | Flutter 禁止息屏、关闭自动锁屏、屏蔽系统屏保 )
android·flutter·ios·屏幕常亮·禁止息屏
心中有国也有家1 小时前
AtomGit Flutter 鸿蒙客户端:情绪日记的时间线实现
学习·flutter·华为·harmonyos
西西学代码2 小时前
Flutter---Container
flutter
西西学代码2 小时前
Flutter---底部导航栏(2)
开发语言·javascript·flutter
浮江雾4 小时前
Flutter第二节----Dart中的常量与变量
开发语言·前端·javascript·flutter·入门
yuanlaile5 小时前
前端转 Flutter 踩坑实录:一套可落地 Flutter 鸿蒙 App 完整学习路线,建议收藏!
flutter·harmonyos·flutter开发鸿蒙·跨平台开发app·flutter深入学习
ZZZMMM.zip5 小时前
基于鸿蒙HarmonyOS NEXT开发AI天气助手应用:智能出行新体验与鸿蒙Flutter框架跨端实践
人工智能·flutter·华为·harmonyos·鸿蒙系统
心中有国也有家6 小时前
AtomGit Flutter 鸿蒙客户端:一键记录情绪的极致体验
学习·flutter·华为·harmonyos
不才难以繁此生6 小时前
HarmonyOS RDB 实战|中式美食菜谱表设计:食材、步骤与购物清单怎么落库
flutter·harmonyos·rdb·中式美食·本地持久化
心中有国也有家6 小时前
AtomGit Flutter 鸿蒙客户端: 周情绪柱状图
学习·flutter·华为·harmonyos