flutter聊天界面-TextField输入框buildTextSpan实现@功能展示高亮功能

这篇具有很好参考价值的文章主要介绍了flutter聊天界面-TextField输入框buildTextSpan实现@功能展示高亮功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

flutter聊天界面-TextField输入框buildTextSpan实现@功能展示高亮功能

最近有位朋友讨论的时候,提到了输入框的高亮展示。在flutter TextField中需要插入特殊样式的标签,比如:“请 @张三 回答一下”,这一串字符在TextField中输入,当输入@时 弹出好友列表选择,然后将 “@张三”高亮显示在TextField中。

https://blog.csdn.net/gloryFlow/article/details/132889374

效果图如下

flutter聊天界面-TextField输入框buildTextSpan实现@功能展示高亮功能,移动开发,flutter开发实战,flutter,flutter,TextField,buildTextSpan,RegExp

一、TextEditingController中的buildTextSpan

在TextField中,我们找到TextEditingController的buildTextSpan方法。

buildTextSpan功能如下:根据当前编辑值生成[TextSpan],默认情况下,使组成范围内的文本显示为带下划线。继承可以重写此方法以自定义文本的外观。

我这里继承TextEditingController,重写buildTextSpan方法,

List<InlineSpan> textSpans = RichTextHelper.getRichText(value.text);
    if (composingRegionOutOfRange) {
      return TextSpan(style: style, children: textSpans);
    }

完整代码如下

import 'package:flutter/material.dart';
import 'package:flutter_lab/rich_text_helper.dart';

class TextFieldController extends TextEditingController {
  /// Builds [TextSpan] from current editing value.
  ///
  /// By default makes text in composing range appear as underlined. Descendants
  /// can override this method to customize appearance of text.
  @override
  TextSpan buildTextSpan(
      {required BuildContext context,
      TextStyle? style,
      required bool withComposing}) {
    assert(!value.composing.isValid ||
        !withComposing ||
        value.isComposingRangeValid);
    // If the composing range is out of range for the current text, ignore it to
    // preserve the tree integrity, otherwise in release mode a RangeError will
    // be thrown and this EditableText will be built with a broken subtree.
    final bool composingRegionOutOfRange =
        !value.isComposingRangeValid || !withComposing;

    print(
        "--- composingRegionOutOfRange:${composingRegionOutOfRange},withComposing:${withComposing},value.isComposingRangeValid:${value.isComposingRangeValid}");
    List<InlineSpan> textSpans = RichTextHelper.getRichText(value.text);
    if (composingRegionOutOfRange) {
      return TextSpan(style: style, children: textSpans);
    }

    print("+++ composingRegionOutOfRange:${composingRegionOutOfRange}");
    final TextStyle composingStyle =
        style?.merge(const TextStyle(decoration: TextDecoration.underline)) ??
            const TextStyle(decoration: TextDecoration.underline);
    return TextSpan(
      style: style,
      children: <TextSpan>[
        TextSpan(text: value.composing.textBefore(value.text)),
        TextSpan(
          style: composingStyle,
          text: value.composing.textInside(value.text),
        ),
        TextSpan(text: value.composing.textAfter(value.text)),
      ],
    );
  }
}

二、设置@高亮

实现将 “@张三”高亮显示在TextField中,需要正则表达是,匹配到@功能正则表达式:String regexStr =
r"@[@]*[@ ]+[^@]* ";

使用RegExp

String regexStr =
        r"@[^@]*[^@ ]+[^@]* ";
    RegExp exp = RegExp('$regexStr');

具体代码如下

import 'package:flutter/material.dart';

class RichTextHelper {
  //图文混排
  static getRichText(String text) {
    List<InlineSpan> textSpans = [];

    String regexStr =
        r"@[^@]*[^@ ]+[^@]* ";
    RegExp exp = RegExp('$regexStr');

    //正则表达式是否在字符串[input]中有匹配。
    if (exp.hasMatch(text)) {
      Iterable<RegExpMatch> matches = exp.allMatches(text);

      int index = 0;
      int count = 0;
      for (var matche in matches) {
        count++;
        String c = text.substring(matche.start, matche.end);
        //匹配到的东西,如表情在首位
        if (index == matche.start) {
          index = matche.end;
        }
        //匹配到的东西,如表情不在首位
        else if (index < matche.start) {
          String leftStr = text.substring(index, matche.start);
          index = matche.end;
          textSpans.add(
            TextSpan(
              text: spaceWord(leftStr),
              style: getDefaultTextStyle(),
            ),
          );
        }

        //匹配到的网址
        if (RegExp(regexStr).hasMatch(c)) {
          textSpans.add(
            TextSpan(
              text: spaceWord(c),
              style:
              TextStyle(color: Colors.blueAccent, fontSize: 16),
            ),
          );
        }

        //是否是最后一个表情,并且后面是否有字符串
        if (matches.length == count && text.length > index) {
          String rightStr = text.substring(index, text.length);
          textSpans.add(
            TextSpan(
              text: spaceWord(rightStr),
              style: getDefaultTextStyle(),
            ),
          );
        }
      }
    } else {
      textSpans.add(
        TextSpan(
          text: spaceWord(text),
          style: getDefaultTextStyle(),
        ),
      );
    }

    return textSpans;
  }

  static TextStyle getDefaultTextStyle() {
    return TextStyle(
      fontSize: 16,
      fontWeight: FontWeight.w400,
      fontStyle: FontStyle.normal,
      color: Colors.black87,
      decoration: TextDecoration.none,
    );
  }

  static String spaceWord(String text) {
    if (text.isEmpty) return text;
    String spaceWord = '';
    for (var element in text.runes) {
      spaceWord += String.fromCharCode(element);
      spaceWord += '\u200B';
    }
    return spaceWord;
  }
}

三、创建TextField

创建需要显示的TextField,设置输入框的onTap、onChanged、focusNode、TextEditingController等

代码如下

// 输入框
class InputTextField extends StatefulWidget {
  const InputTextField({
    Key? key,
    this.inputOnTap,
    this.inputOnChanged,
    this.inputOnSubmitted,
    this.inputOnEditingCompleted,
    this.autofocus = false,
    required this.textEditingController,
  }) : super(key: key);

  final inputOnTap;
  final inputOnChanged;
  final inputOnSubmitted;
  final inputOnEditingCompleted;
  final bool autofocus;
  final TextEditingController textEditingController;

  @override
  State<InputTextField> createState() => _InputTextFieldState();
}

class _InputTextFieldState extends State<InputTextField> {
  FocusNode editFocusNode = FocusNode();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  //获取焦点
  void getFocusFunction(BuildContext context) {
    FocusScope.of(context).requestFocus(editFocusNode);
  }

  //失去焦点
  void unFocusFunction() {
    editFocusNode.unfocus();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    editFocusNode.unfocus();
    editFocusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.only(
        left: 10.0,
        top: 5.0,
        bottom: 5.0,
      ),
      constraints: BoxConstraints(
        minHeight: 40.0,
        maxHeight: 120.0,
      ),
      child: TextField(
        onTap: () {
          widget.inputOnTap();
        },
        onChanged: (string) {
          widget.inputOnChanged(string);
        },
        onEditingComplete: () {
          widget.inputOnEditingCompleted();
        },
        onSubmitted: (string) {
          widget.inputOnSubmitted(string);
        },
        minLines: 1,
        maxLines: null,
        keyboardType: TextInputType.multiline,
        textAlignVertical: TextAlignVertical.center,
        autofocus: widget.autofocus,
        focusNode: editFocusNode,
        controller: widget.textEditingController,
        textInputAction: TextInputAction.send,
        decoration: InputDecoration(
          contentPadding: EdgeInsets.symmetric(vertical: 10, horizontal: 8.0),
          filled: true,
          isCollapsed: true,
          floatingLabelBehavior: FloatingLabelBehavior.never,
          hintText: "说点什么吧~",
          hintStyle: TextStyle(
            fontSize: 14,
            fontWeight: FontWeight.w400,
            fontStyle: FontStyle.normal,
            color: ColorUtil.hexColor(0xACACAC),
            decoration: TextDecoration.none,
          ),
          enabledBorder: OutlineInputBorder(
            /*边角*/
            borderRadius: const BorderRadius.all(
              Radius.circular(5.0), //边角为30
            ),
            borderSide: BorderSide(
              color: ColorUtil.hexColor(0xf7f7f7), //边框颜色为绿色
              width: 1, //边线宽度为1
            ),
          ),
          focusedBorder: OutlineInputBorder(
            borderRadius: const BorderRadius.all(
              Radius.circular(5.0), //边角为30
            ),
            borderSide: BorderSide(
              color: ColorUtil.hexColor(0xECECEC), //边框颜色为绿色
              width: 1, //宽度为1
            ),
          ),
        ),
      ),
    );
  }
}

四、TextField赋text演示

最后我们可以在输入框TextField设置文本

TextFieldController textEditingController = TextFieldController();

textEditingController.text = "你好@张三 欢迎,哈哈,haha";

完整代码如下

class TextFieldRich extends StatefulWidget {
  const TextFieldRich({super.key});

  @override
  State<TextFieldRich> createState() => _TextFieldRichState();
}

class _TextFieldRichState extends State<TextFieldRich> {
  TextFieldController textEditingController = TextFieldController();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    textEditingController.text = "你好@张三 欢迎,哈哈,haha";
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    Size scrSize = MediaQuery.of(context).size;
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text('TextField测试页面'),
      ),
      body: Container(
        width: scrSize.width,
        height: scrSize.height,
        color: Colors.greenAccent,
        alignment: Alignment.center,
        padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 20.0),
        child: InputTextField(textEditingController: textEditingController),
      ),
    );
  }
}

至此可以看到效果图中@张三 高亮显示了。

五、小结

flutter聊天界面-TextField输入框buildTextSpan实现@功能展示高亮功能。该示例中,光标会有问题,暂时没做修改,后续抽空修改。

https://blog.csdn.net/gloryFlow/article/details/132889374

学习记录,每天不停进步。文章来源地址https://www.toymoban.com/news/detail-733087.html

到了这里,关于flutter聊天界面-TextField输入框buildTextSpan实现@功能展示高亮功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Flutter 问题系列第 80 篇】TextField 输入框组件限制可输入的最大长度后,输入的内容中包含表情符号时,获取输入的内容数还是会超出限制的问题

    这是【Flutter 问题系列第 80 篇】,如果觉得有用的话,欢迎关注专栏。 博文当前所用 Flutter SDK:3.10.5、Dart SDK:3.0.5 一:问题描述 在输入用户名称、简介等内容时,一般我们都会限制输入框内最大可输入数(通过 TextField 组件的 maxLength 属性),如下图限制简介最多10个字 正常

    2024年01月21日
    浏览(59)
  • 如何实现仿微信界面[我的+首页聊天列表+长按菜单功能+添加菜单功能]

    如何实现仿微信界面[我的+首页聊天列表+长按菜单功能+添加菜单功能] 采用 uni-app 实现,可以适用微信小程序、其他各种小程序以及 APP、Web等多个平台 具体实现步骤如下: 下载开发者工具 HbuilderX 进入 【 Dcloud 插件市场 】 搜索 【仿微信界面[我的+首页聊天列表+长按菜单功

    2024年04月08日
    浏览(77)
  • 微信小程序简单输入框界面(实现选择标签功能)

    1、js代码: 2、wxml代码: 3、wxss代码: 布局简单,对于初学者可以用来看看,随便写的,如果出现运行异常,请使用真机预览呦~

    2024年03月12日
    浏览(84)
  • flutter聊天界面-聊天气泡长按弹出复制、删除按钮菜单

    flutter聊天界面-聊天气泡长按弹出复制、删除按钮菜单 在之前实现了flutter聊天界面的富文本展示内容,这里记录一下当长按聊天气泡的时候弹出复制、删除等菜单功能 当长按聊天气泡的时候弹出复制、删除等菜单,可新增更多按钮 实现箭头效果,这里实现自定义的CustomPai

    2024年02月13日
    浏览(43)
  • flutter聊天界面-加号【➕】更多展开相机、相册等操作Panel

    flutter聊天界面-加号【➕】更多展开相机、相册等操作Panel 在之前实现了flutter聊天界面的自定义表情的展示,这里记录一下更多操作展开的相机、相册等操作功能实现。 更多操作展开的相机、相册等操作功能实现。 展开的操作按钮可能比较多,一页显示8个、多个可以左右滑

    2024年02月13日
    浏览(42)
  • Android Studio 制作微信,登入界面,输入密码界面,跳转手机登录界面,以及聊天界面

    2.打开Android Studio。 3.选择 \\\"Create New Project\\\"。 4.在 \\\"Create New Project\\\" 对话框中,输入项目名称、选择存储位置等信息。 5.选择最低支持的Android版本,并选择一个适合的活动模板(例如,Empty Activity)。 6.点击 \\\"Finish\\\" 创建新的Android项目。 8.打开 \\\"activity_main.xml\\\" 文件,该文件用于定

    2024年02月07日
    浏览(44)
  • flutter聊天界面-Text富文本表情emoji、url、号码展示

    flutter聊天界面-Text富文本表情emoji、url、号码展示 Text富文本表情emoji展示,主要通过实现Text.rich展示文本、emoji、自定义表情、URL等 Text用于显示简单样式文本 TextSpan它代表文本的一个“片段”,不同“片段”可按照不同的样式显示。 示例片段 Text富文本表情emoji展示主要通过

    2024年02月12日
    浏览(46)
  • Flutter——最详细(TextField)使用教程

    文本输入框,拥有复杂的属性。可指定控制器、文字样式、装饰线、行数限制、游标样式等。监听输入框变动事件。 搜索框,输入账号密码等 属性 作用 controller 输入框监听器 decoration 输入框装饰属性 textAlign 内容对齐方式 textAlignVertical 文本垂直对齐 textDirection 文字方向 ma

    2024年02月13日
    浏览(42)
  • Flutter TextField 交互实例 —— 新手礼包

    大家好,我是 17。 新手礼包一共 3 篇文章,每篇都是描述尽量详细,实例讲解,包会! Flutter Row 实例 —— 新手礼包 Flutter TextField UI 实例 —— 新手礼包 Flutter TextField 交互实例 —— 新手礼包 本篇包含所有常见 TextField 交互示例。 在上一篇 Flutter TextField UI 实例 中第一个示例

    2023年04月09日
    浏览(40)
  • Flutter TextField UI 实例 —— 新手礼包

    大家好,我是17。 新手礼包一共 3 篇文章,每篇都是描述尽量详细,实例讲解,包会! Flutter Row 实例 —— 新手礼包 Flutter TextField UI 实例 —— 新手礼包 Flutter TextField 交互实例 —— 新手礼包 本篇介绍了 TextField UI 的常见写法,从TextField的尺寸,border,icon,文本到光标,无所

    2023年04月08日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包