Flutter社交应用自定义表情键盘实现方案问询
自定义表情集合实现思路
一、基础映射配置
先把表情编码和资源路径的Map固定好,这是所有逻辑的核心:
final Map<String, String> customEmojis = { "#123": "assets/emojis/cat.png", "#777": "assets/emojis/dog.png", // 按需添加更多表情编码与路径 };
二、输入框(TextFormField)显示表情方案
TextFormField本身无法直接混排文本和图片,用「隐藏输入框+富文本显示」的组合就能解决:
- 准备
TextEditingController,负责存储实际输入文本(比如"今天#123好可爱#777",存的是表情编码)。 - 用
Stack布局,底层放透明的TextFormField(设置style: TextStyle(color: Colors.transparent)),处理输入、光标控制;上层放RichText,把控制器里的文本转换成带图片的富文本。 - 编写转换函数,把纯文本转成可渲染的
InlineSpan列表:
List<InlineSpan> convertTextToEmojiSpans(String text) { final spans = <InlineSpan>[]; final regex = RegExp(r'#\d+'); // 匹配表情编码格式 int start = 0; regex.allMatches(text).forEach((match) { // 添加编码前的普通文本 if (match.start > start) { spans.add(TextSpan(text: text.substring(start, match.start))); } // 匹配到编码则替换为图片 final emojiCode = match.group(0)!; final emojiPath = customEmojis[emojiCode]; if (emojiPath != null) { spans.add(WidgetSpan( child: Image.asset( emojiPath, width: 20, height: 20, fit: BoxFit.contain, ), )); } else { // 找不到对应表情时显示原编码 spans.add(TextSpan(text: emojiCode)); } start = match.end; }); // 添加剩余的普通文本 if (start < text.length) { spans.add(TextSpan(text: text.substring(start))); } return spans; }
- 监听
TextEditingController的文本变化,实时更新RichText内容。
三、帖子展示时的表情渲染
直接复用上面的转换函数,用RichText渲染帖子内容:
RichText( text: TextSpan( style: TextStyle(color: Colors.black, fontSize: 16), children: convertTextToEmojiSpans(postContent), ), )
如果表情是网络资源,把Image.asset换成Image.network即可。
四、网格表情选择器实现
用GridView.count做布局,每个表情项绑定点击事件,点击时把编码插入到输入框光标位置:
GridView.count( crossAxisCount: 5, padding: EdgeInsets.all(8), children: customEmojis.entries.map((entry) { return GestureDetector( onTap: () { final controller = _yourTextEditingController; final emojiCode = entry.key; // 获取光标位置并插入编码 final selection = controller.selection; controller.text = controller.text.replaceRange( selection.baseOffset, selection.extentOffset, emojiCode, ); // 更新光标到插入后的位置 controller.selection = TextSelection.fromPosition( TextPosition(offset: selection.baseOffset + emojiCode.length), ); }, child: Image.asset( entry.value, width: 30, height: 30, ), ); }).toList(), )
额外建议
- 可以给表情编码加特殊标识(比如
[emoji:123]),避免和普通文本里的#数字混淆,正则匹配也更准确。 - 统一表情图片尺寸,显示时保持一致大小,避免排版混乱。
- 表情数量较多时,可添加分页或搜索功能,提升选择效率。
内容的提问来源于stack exchange,提问作者Alana Amged
相关产品推荐
相关产品推荐

