FSA全栈行动 FSA全栈行动
首页
  • 移动端文章

    • Android
    • iOS
    • Flutter
  • 学习笔记

    • 《Kotlin快速入门进阶》笔记
    • 《Flutter从入门到实战》笔记
    • 《Flutter复习》笔记
前端
后端
  • 学习笔记

    • 《深入浅出设计模式Java版》笔记
  • 逆向
  • 分类
  • 标签
  • 归档
  • LinXunFeng
  • GitLqr

公众号:FSA全栈行动

记录学习过程中的知识
首页
  • 移动端文章

    • Android
    • iOS
    • Flutter
  • 学习笔记

    • 《Kotlin快速入门进阶》笔记
    • 《Flutter从入门到实战》笔记
    • 《Flutter复习》笔记
前端
后端
  • 学习笔记

    • 《深入浅出设计模式Java版》笔记
  • 逆向
  • 分类
  • 标签
  • 归档
  • LinXunFeng
  • GitLqr
  • AndroidUI

  • Android第三方SDK

  • Android混淆

  • Android仓库

  • Android新闻

  • Android系统开发

  • Android源码

  • Android注解AOP

  • Android脚本

  • AndroidTv开发

  • AndroidNDK

  • Android音视频

  • Android热修复

  • Android性能优化

  • Android云游戏

  • Android插件化

  • iOSUI

  • iOS工具

  • iOS底层原理与应用

  • iOS组件化

  • iOS音视频

  • iOS疑难杂症

  • iOS之Swift

  • iOS之RxSwift

  • iOS开源项目

  • iOS逆向

  • Flutter开发

    • Dart - 抽象类的实例化
    • Flutter - 打印好用的Debug日志
    • Flutter - 混合开发
    • Flutter - 解决混合开发iOS脚本打包遇到的问题
    • Flutter - 低版本在iOS14上遇到的问题与解决方案
    • Flutter - 解决原生弹窗的触摸事件被Flutter响应的问题
    • Flutter - 实现列表上下拉切换header
    • Flutter - 获取ListView当前正在显示的Widget信息
    • Flutter - 列表滚动定位超强辅助库,墙裂推荐!🔥
    • Flutter - 快速实现聊天会话列表的效果,完美💯
    • Flutter - 聊天输入框更新文本时的必备优化点🔖
    • Flutter - 我给官方提PR,解决run命令卡住问题 😃
    • Flutter - 探索run命令到底做了什么 🤔
    • Flutter - 引擎调试(iOS篇)🛠
    • Flutter - 引擎调试bug到提交PR实战 🐞
    • Flutter - 船新升级😱支持观察第三方构建的滚动视图💪
    • Flutter - 瀑布流交替播放视频 🎞
    • Flutter - IM保持消息位置大升级(支持ChatGPT生成式消息) 🤖
    • Flutter - 滚动视图中的表单防遮挡 🗒
    • Flutter - 秒杀1/2曝光统计 📊
    • 一天内加入 Flutter 和 FlutterCandies 两大组织是什么体验 🧐
    • Flutter - 如何快速搓一个微信通讯录列表(azlist) 📓
    • Flutter - 混编项目集成Shorebird热更新🐦(安卓篇)
    • Flutter - 混编项目集成Shorebird热更新🐦(iOS篇)
    • Flutter - 解决返回原生页面时dispose方法未被触发的问题 🐞
    • Flutter - 升级3.19之后页面多次rebuild?🤨
    • Flutter - 热更新 Shorebird 1.0 正式版来了 🐦
    • Flutter - 使用Pigeon实现视频缓存插件 🐌
    • Flutter - 轻松搞定屏幕旋转功能 😎
    • Flutter - 解决Connection closed before full header was received
    • Flutter - 实现聊天键盘与功能面板的丝滑切换 🍻
    • Flutter - 支持观察NestedScrollView,兼容性更强 😈
    • Flutter - 聊天键盘与面板丝滑切换的强势升级 🍻
      • 一、概述
      • 二、使用
        • 调整键盘高度监听管理逻辑
        • 兼容外接键盘
        • 隐藏面板
        • 自定义底部安全区高度
        • 调整键盘面板高度
        • 缓存键盘高度
        • 支持表情面板与输入框焦点共存
      • 三、最后
    • Flutter - 升级到3.24后页面还会多次rebuild吗?🧐
    • Flutter - 轻松实现PageView卡片偏移效果
    • Flutter - 轻松搞定炫酷视差(Parallax)效果
    • Flutter - 危!3.24版本苹果审核被拒!
    • Flutter - 子部件任意位置观察滚动数据
    • Flutter - iOS编译加速
    • Flutter - Xcode16 还原编译速度
  • 移动端
  • Flutter开发
LinXunFeng
2024-08-04
目录

Flutter - 聊天键盘与面板丝滑切换的强势升级 🍻

欢迎关注微信公众号:[FSA全栈行动 👋]

# 一、概述

距离 chat_bottom_container (opens new window) 首个可用版本 (0.0.2) 的发布已经过去了 1 个多月,在这期间根据大家的使用反馈,我们也做了一些优化调整,今天就来盘点一下到底做了哪些优化,新增了什么功能,以及一些常见操作。

请注意

  • 本篇仅介绍更新的优化及功能,基础使用请查看: Flutter - 实现聊天键盘与功能面板的丝滑切换 🍻
  • 截至本篇发布时,最新版本为 0.2.0,可以关注我们的微信公众号 FSA全栈行动 (opens new window) 获取最新的资讯

开源不易,如果你也觉得这个库好用,请不吝给个 Star 👍 ,并多多支持!

https://github.com/LinXunFeng/flutter_chat_packages (opens new window)

# 二、使用

# 调整键盘高度监听管理逻辑

0.1.0 版本前,只考虑了页面栈这种常规情况,当键盘高度变化时只处理栈顶的监听。

但其实还有一种常见打破该规则的场景,就是悬浮聊天页,它会一直在页面上,可能为了能快速从悬浮小球展开聊天页面,收起时只是做了隐藏,而不会销毁页面,在这种情况下,它依旧在监听管理里的栈顶,所以在收起后,上一个聊天页的键盘高度监听就会失效。

这个在 0.1.0 版本中得到修复,内部会倒序遍历调用所有的监听回调。

不过你不用担心这一改动会导致其它聊天页面出现多余的视图刷新,因为在键盘高度监听回调里会先判断输入框是否有焦点,若无则直接返回了。

# 兼容外接键盘

当连接外接键盘时,软键盘会消失,高度会降为 0,这里可以用 iOS 模拟器结合 Toggle Software Keyboard (快捷键: cmd + k) 来模拟连接与断开外接键盘的效果。

# 隐藏面板

有小伙伴提出,不知道如何程序式的隐藏面板,其实很简单,就两步

  1. 让输入框失去焦点
  2. 更新内部状态为 ChatBottomPanelType.none
hidePanel() {
  // 0.2.0 前
  inputFocusNode.unfocus();
  if (ChatBottomPanelType.none == controller.currentPanelType) return;
  controller.updatePanelType(ChatBottomPanelType.none);
  
  // 0.2.0 后,可以这么写
  controller.updatePanelType(
    ChatBottomPanelType.none,
    forceHandleFocus: ChatBottomHandleFocus.unfocus,
  );
}

# 自定义底部安全区高度

在默认情况下,chat_bottom_container 在收起模式 (.none) 下会自动帮你添加底部安全区高度,但在一些场景下你可能不希望如此。比如:

  • 安卓的底部安全区的高度,很多小伙伴都是简单粗暴的设置个高度了事
  • App 首页有底部 BottomNavigationBar,不需要安全区高度

在此,你可以通过将 safeAreaBottom 参数来自定义这个高度,如下设置为 0。

return ChatBottomPanelContainer<PanelType>(
  ...
  safeAreaBottom: 0,
  ...
);

# 调整键盘面板高度

如示例中位于首页的聊天页面

在键盘弹出时,如下图所示

实际 期望

很明显,我们希望键盘容器高度能够减去外层底部固定的 BottomNavigationBar 高度。

ChatBottomPanelContainer 提供了 changeKeyboardPanelHeight 回调,在回调中可以拿到当前的键盘高度,经过计算后,将合适的键盘容器高度返回即可。

return ChatBottomPanelContainer<PanelType>(
  ...
  changeKeyboardPanelHeight: (keyboardHeight) {
    final renderObj = bottomNavigationBarKey.currentContext?.findRenderObject();
    if (renderObj is! RenderBox) return keyboardHeight;
    return keyboardHeight - renderObj.size.height;
  },
  ...
);

# 缓存键盘高度

先来看未做键盘高度缓存处理之前,会发生什么?

上图一共进入了三次聊天页

  • 第一次是先点击键盘,再切到表情面板,体验起来还是挺不错的。
  • 为了避免一闪而过,没有注意到,所以第二次和第三次的操作是一样的,先唤起表情面板,再切到键盘,可以看到在切到键盘时会抖动。

这是因为每次进入聊天页,键盘的高度为初始值 0,在 0.2.0 版本中对此进行了优化,加入了键盘高度缓存逻辑,从而尽量避免该抖动问题的出现。

❗️ 但需要注意的是,假如你卸载重装 App,该缓存会丢失,即你还是有可能会看到最多一次的抖动。

除此之外,你还可以使用这个缓存的键盘高度来实现表情面板与键盘高度保持一致的效果,这样在切换的时候体验上会更好些。😉

Widget _buildEmojiPickerPanel() {
  // 如果键盘高度还没有缓存过,则使用默认高度 300
  double height = 300;
  final keyboardHeight = controller.keyboardHeight;
  if (keyboardHeight != 0) {
    height = keyboardHeight;
  }

  return Container(
    padding: EdgeInsets.zero,
    height: height,
    color: Colors.blue[50],
    child: const Center(
      child: Text('Emoji Panel'),
    ),
  );
}

效果如下

# 支持表情面板与输入框焦点共存

这也是提升用户体验的重要一点,效果见上图。

先按如下设置你的输入框

bool readOnly = false;
TextEditingController textEditingController = TextEditingController();

...
TextField(
  controller: textEditingController,
  focusNode: inputFocusNode,
  // 为 true 时不显示键盘,默认为 false
  readOnly: readOnly,
  // 获取焦点后显示光标,设置为 true 才不受 readOnly 的影响
  showCursor: true,
),
...

接下来就是切换表情面板的操作

switchToEmojiPanel() {
  readOnly = true;
  // 这里你可以只刷新输入框
  setState(() {});

  // 等待下一帧
  WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
    controller.updatePanelType(
      // 内部切至 other 状态
      ChatBottomPanelType.other,
      // 关联外部的面板类型为表情面板
      data: PanelType.emoji,
      // 输入框获取焦点
      forceHandleFocus: ChatBottomHandleFocus.requestFocus,
    );
  });
}

在 updatePanelType 方法中,如果是切至 .other 状态,是会帮你执行失去焦点操作的,所以这里提供了一个 forceHandleFocus 参数,如果你对方法内部对焦点的处理不满意,你可以使用它来强制指定焦点的处理方式。

# 三、最后

好了,上述便是该库的更新内容, 惯例附上 GitHub 地址: https://github.com/LinXunFeng/flutter_chat_packages/tree/main/packages/chat_bottom_container (opens new window) ,如果接入上有什么问题,可以在链接中查看 demo 演示代码。

开源不易,如果你也觉得这个库好用,请不吝给个 Star 👍 ,并多多支持!

本篇到此结束,感谢大家的支持,我们下次再见! 👋

#Dart#Flutter#Chat
Flutter - 支持观察NestedScrollView,兼容性更强 😈
Flutter - 升级到3.24后页面还会多次rebuild吗?🧐

← Flutter - 支持观察NestedScrollView,兼容性更强 😈 Flutter - 升级到3.24后页面还会多次rebuild吗?🧐→

最近更新
01
Flutter - Xcode16 还原编译速度
04-05
02
AI - 免费的 Cursor 平替方案
03-30
03
Android - 2025年安卓真的闭源了吗
03-28
更多文章>
Theme by Vdoing | Copyright © 2020-2025 FSA全栈行动
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×