Flutter文本框添加图片表情(粗制滥造版)

效果图:

使用 Unicode 的私有区做表情的占位符

继承重写 TextEditingController,在 buildTextSpan 内显示时调整为表情图片。

表情键值对:

js 复制代码
final Map<int, String> emojiMap = {
    0xE001: 'assets/images/1.png',
    0xE002: 'assets/images/2.png',
    0xE003: 'assets/images/3.png',
  };

遍历字符串把占位符显示为表情的方法:

js 复制代码
  List<InlineSpan> _parseText(String text, TextStyle? style) {
    final spans = <InlineSpan>[];
    final buffer = StringBuffer();
    for (final codePoint in text.runes) {
      // 如果是表情
      if (codePoint >= 0xE000 && codePoint <= 0xF8FF) {
        // 将 buffer 内的字符加入 spans 并清空 buffer。
        if (buffer.isNotEmpty) {
          spans.add(TextSpan(text: buffer.toString(), style: style));
          buffer.clear();
        }
        // 处理表情
        final asset = emojiMap[codePoint];
        if (asset != null) {
          spans.add(
            WidgetSpan(
              child: Image.asset(
                asset,
                width: style?.fontSize,
                height: style?.fontSize,
              ),
            ),
          );
        } else {
          buffer.writeCharCode(codePoint);
        }
      } else {
        buffer.writeCharCode(codePoint);
      }
    }
    if (buffer.isNotEmpty) {
      spans.add(TextSpan(text: buffer.toString(), style: style));
    }
    return spans;
  }

 

buildTextSpan:

js 复制代码
  @override
  TextSpan buildTextSpan({
    required BuildContext context,
    TextStyle? style,
    required bool withComposing,
  }) {
    assert(
      !value.composing.isValid || !withComposing || value.isComposingRangeValid,
    );
    final bool composingRegionOutOfRange =
        !value.isComposingRangeValid || !withComposing;

    if (composingRegionOutOfRange) {
      // 修改为使用 _parseText()
      // 原本的:return TextSpan(style: style, text: text);
      return TextSpan(style: style, children: _parseText(text, style));
    }

    final TextStyle composingStyle =
        style?.merge(const TextStyle(decoration: TextDecoration.underline)) ??
        const TextStyle(decoration: TextDecoration.underline);

    // 这里也是修改为使用 _parseText()
    return TextSpan(
      style: style,
      children: <TextSpan>[
        TextSpan(
          children: _parseText(value.composing.textBefore(value.text), style),
        ),
        TextSpan(
          style: composingStyle,
          children: _parseText(value.composing.textInside(value.text), style),
        ),
        TextSpan(
          children: _parseText(value.composing.textAfter(value.text), style),
        ),
      ],
    );
  }

添加表情:

js 复制代码
  void addEmoji(int codePoint) {
    // 获取当前选区,如果无效(如未聚焦),则默认光标在文本末尾
    final TextSelection currentSelection = selection.isValid
        ? selection
        : TextSelection.collapsed(offset: text.length);

    // 根据选区情况构造新文本和光标位置
    final String newText;
    final int newCursorOffset;

    if (currentSelection.isCollapsed) {
      // 折叠光标:直接插入
      final int pos = currentSelection.baseOffset;
      newText =
          text.substring(0, pos) +
          String.fromCharCode(codePoint) +
          text.substring(pos);
      newCursorOffset = pos + 1;
    } else {
      // 有选中文本:先删除选中内容,再在开始位置插入
      final int start = currentSelection.start;
      final int end = currentSelection.end;
      newText =
          text.substring(0, start) +
          String.fromCharCode(codePoint) +
          text.substring(end);
      newCursorOffset = start + 1;
    }

    // 更新控制器值,并设置光标折叠在新字符之后
    value = value.copyWith(
      text: newText,
      selection: TextSelection.collapsed(offset: newCursorOffset),
      // 清除组合范围,因为插入操作会中断输入法组合
      composing: TextRange.empty,
    );
  }
相关推荐
世人万千丶1 天前
Flutter 框架跨平台鸿蒙开发 - 鸿蒙版本五子棋游戏应用
学习·flutter·游戏·华为·harmonyos·鸿蒙
autumn20051 天前
Flutter 框架跨平台鸿蒙开发 - 连连看游戏应用
flutter·华为·harmonyos
程序员老刘1 天前
AI时代我们是否还需要学编程?丨《Flutter跨平台开发核心技巧与应用》新书上市啦
flutter·ai编程·客户端
浮芷.1 天前
Flutter 框架跨平台鸿蒙开发 - flutter版本样式的美食菜谱应用
flutter·harmonyos·美食
小雨天気.1 天前
Flutter 框架跨平台鸿蒙开发 - 生活中的书法练习应用开发文档
flutter·生活·harmonyos
2301_822703201 天前
开源鸿蒙跨平台Flutter开发:FASTA 格式解析进阶:序列校验与异常处理机制实现
flutter·华为·开源·鸿蒙
AI_零食1 天前
Flutter 框架跨平台鸿蒙开发 - 鸿蒙麻将游戏应用
学习·flutter·游戏·华为·交互·harmonyos
dragon7251 天前
Flutter错误处理机制
前端·flutter
独特的螺狮粉1 天前
Flutter 框架跨平台鸿蒙开发 - 睡眠白噪音开发纪录
flutter·华为·harmonyos·鸿蒙
提子拌饭1331 天前
Flutter 框架跨平台鸿蒙开发 - 商用项目看板应用
flutter·华为·harmonyos