Flutter - 实现聊天键盘与功能面板的丝滑切换 🍻
# 一、概述
相信大家接触【即时通信应用】的时候都会遇到这个问题,那就是如何去实现聊天页面的键盘和其它功能面板的丝滑切换,这种问题也有人向 Flutter
官方提出过 issue
,如下这两个:
- https://github.com/flutter/flutter/issues/121059 (opens new window)
- https://github.com/flutter/flutter/issues/32583 (opens new window)
可以看到,从表情面板切到文本输入框时会抖动一下,影响用户体验。
但几年过去了依旧没有得到解决,再加上我自己也有这个小烦恼,所以我与 GitLqr (opens new window)(GitHub: https://github.com/GitLqr (opens new window))一起开发了这个 chat_bottom_container
,来帮助我们快速实现这个丝滑切换的效果。
# 二、效果
这里先附上效果图,好让大家直观感受一下~
下面我们一起来看看怎么使用吧。
# 三、集成
将 chat_bottom_container
添加到你的 pubspec.yaml
文件中
dependencies:
chat_bottom_container: latest_version
具体版本大家到 pub.dev
上复制粘贴最新的吧,附上链接:https://pub.dev/packages/chat_bottom_container (opens new window)
Android
端需要添加 jitpack
仓库到你的项目根目录下的 build.gradle
文件中:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
在需要使用的地方导入 chat_bottom_container
:
import 'package:chat_bottom_container/chat_bottom_container.dart';
# 四、使用
# 页面布局
首先第一件事,确定整体的页面布局
Widget build(BuildContext context) {
return Scaffold(
// 设置为 false
resizeToAvoidBottomInset: false,
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: ListView.builder(
...
),
),
// 输入框视图
_buildInputView(),
// 底部容器
_buildPanelContainer(),
],
),
);
}
这里就两个注意点:
- 底部容器放在最底下
resizeToAvoidBottomInset
必须设置为false
# 底部容器
输入框视图的样式各种各样,这里就不说了,大家爱怎么实现都行,接下来我们来看看怎么使用 chat_bottom_container
这个库实现底部容器,代码如下:
/// 自定义底部面板类型
enum PanelType {
// 收起
none,
// 键盘
keyboard,
// 表情
emoji,
// 其它工具
tool,
}
/// chat_bottom_container 的控制器,用来告知 chat_bottom_container 需要切面板类型了
/// 注:这里传泛型传了 PanelType,是为了与外部的面板类型相关联
final controller = ChatBottomPanelContainerController<PanelType>();
/// 输入框的焦点对象
final FocusNode inputFocusNode = FocusNode();
/// 记录当前的底部面板类型
PanelType currentPanelType = PanelType.none;
Widget _buildPanelContainer() {
return ChatBottomPanelContainer<PanelType>(
controller: controller,
inputFocusNode: inputFocusNode,
otherPanelWidget: (type) {
// 返回自定义的面板视图
if (type == null) return const SizedBox.shrink();
switch (type) {
case PanelType.emoji: // 表情面板
return _buildEmojiPickerPanel();
case PanelType.tool: // 其它工具面板
return _buildToolPanel();
default:
return const SizedBox.shrink();
}
},
onPanelTypeChange: (panelType, data) {
// 可用来记录当前的面板类型(该操作非必须~)
// panelType: chat_bottom_container 内部定义的面板类型,就三种(.none|.keyboard|.other)
// data: 外部自定义的底部面板类型
switch (panelType) {
case ChatBottomPanelType.none:
currentPanelType = PanelType.none;
break;
case ChatBottomPanelType.keyboard:
currentPanelType = PanelType.keyboard;
break;
case ChatBottomPanelType.other:
if (data == null) return;
switch (data) {
case PanelType.emoji:
currentPanelType = PanelType.emoji;
break;
case PanelType.tool:
currentPanelType = PanelType.tool;
break;
default:
currentPanelType = PanelType.none;
break;
}
break;
}
},
// 底部面板容器背景色
panelBgColor: panelBgColor,
);
}
chat_bottom_container
内部定义的面板类型,就三种
enum ChatBottomPanelType {
// 无
none,
// 键盘
keyboard,
// 其它
other,
}
因为 chat_bottom_container
并不关心你外部除了键盘外还有多少种面板类型,所以这里统一视为是 ChatBottomPanelType.other
。
而我们外部开发者不可能不在乎,所以我们在点击表情面板按钮时,调用 controller.updatePanelType
去切换底部面板类型,并为 data
这个参数传入外部自定义的底部面板类型,如下代码所示
controller.updatePanelType(
// 设置 ChatBottomPanelContainer 当前的底部面板类型
// 可传入 ChatBottomPanelType.keyboard | ChatBottomPanelType.other | ChatBottomPanelType.none
ChatBottomPanelType.other,
// 回调给外部开发者自定义的 PanelType,当 ChatBottomPanelType.other 时必传
data: PanelType.emoji, // PanelType.tool
);
所以上面提到的泛型就是为了关联 otherPanelWidget
和 onPanelTypeChange
回调中的类型,方便我们拿来使用。
# 五、最后
好了,上述便是该库的核心使用步骤, 我已将上述的 Flutter
聊天底部面板容器库发布至 GitHub
: https://github.com/LinXunFeng/flutter_chat_packages/tree/main/packages/chat_bottom_container (opens new window) ,如果接入上有什么问题,可以在链接中查看 demo
演示代码。
开源不易,如果你也觉得这个库好用,请不吝给个 Star
👍 ,并多多支持!
本篇到此结束,感谢大家的支持,我们下次再见! 👋
![](https://cdn.jsdelivr.net/gh/FullStackAction/PicBed@resource/image/FSA_QR_bottom.png)
- 01
- Flutter - 升级到3.24后页面还会多次rebuild吗?🧐08-11
- 02
- Flutter - 聊天键盘与面板丝滑切换的强势升级 🍻08-04
- 03
- Android - 云游戏本地悬浮输入框实现07-07