You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中实现全名@提及功能技术求助

实现Flutter全名@提及功能的可行方案

方案1:修改flutter_social_textfield源码适配全名提及

既然你已经在用这个包,最直接的方式是调整它的核心逻辑来支持全名:

  • 找到包中负责提及匹配的文件(比如mention_matcher.dart或类似文件),把原本匹配用户名的正则(通常是@([a-zA-Z0-9_]+))替换为支持空格的匹配逻辑,或者改为基于前缀匹配全名列表,而非用正则硬限制字符。
  • 替换数据源:把原本传入的用户名列表换成全名列表(比如['John Doe', 'Jane Smith']),输入@后,候选列表会根据输入前缀(比如@Joh)过滤对应的全名。
  • 调整插入逻辑:确保选中候选全名后,文本中插入@全名格式的内容,而非仅用户名。

方案2:自定义实现全名提及功能

如果不想修改第三方包,自己实现也可快速落地,核心是TextField+Overlay组合:

  1. 监听输入触发状态
    用TextEditingController监听文本变化,判断是否进入@提及模式:
final TextEditingController _controller = TextEditingController();
bool _isMentionMode = false;
String _mentionPrefix = '';

@override
void initState() {
  super.initState();
  _controller.addListener(() {
    final text = _controller.text;
    final lastAtIndex = text.lastIndexOf('@');
    if (lastAtIndex != -1) {
      _isMentionMode = true;
      _mentionPrefix = lastAtIndex < text.length - 1 ? text.substring(lastAtIndex + 1) : '';
    } else {
      _isMentionMode = false;
    }
    setState(() {});
  });
}
  1. 弹出候选全名列表
    通过Overlay在TextField下方展示过滤后的全名候选,点击后插入文本:
List<String> fullNames = ['John Doe', 'Jane Smith', 'Bob Johnson'];
List<String> get filteredNames => fullNames.where((name) => name.toLowerCase().contains(_mentionPrefix.toLowerCase())).toList();

// 在build方法中插入Overlay(需注意生命周期管理)
if (_isMentionMode && filteredNames.isNotEmpty) {
  final overlayEntry = OverlayEntry(
    builder: (context) => Positioned(
      top: MediaQuery.of(context).size.height * 0.2, // 根据TextField位置调整
      left: 20,
      right: 20,
      child: Material(
        elevation: 4,
        child: ListView.builder(
          shrinkWrap: true,
          itemCount: filteredNames.length,
          itemBuilder: (context, index) => ListTile(
            title: Text(filteredNames[index]),
            onTap: () {
              final currentText = _controller.text;
              final newText = currentText.substring(0, currentText.lastIndexOf('@')) + '@${filteredNames[index]} ';
              _controller.text = newText;
              _controller.selection = TextSelection.fromPosition(TextPosition(offset: newText.length));
              _isMentionMode = false;
              overlayEntry.remove();
              setState(() {});
            },
          ),
        ),
      ),
    ),
  );
  Overlay.of(context).insert(overlayEntry);
}
  1. 高亮提及文本
    通过TextSpan自定义文本样式,给@提及的全名添加高亮效果(可结合RichText或自定义TextField的样式处理器实现)。

方案3:用flutter_typeahead快速适配

借助flutter_typeahead的自动补全能力,快速搭建@提及功能:

TypeAheadField(
  textFieldConfiguration: TextFieldConfiguration(
    controller: _controller,
    decoration: InputDecoration(hintText: '输入@提及联系人'),
  ),
  suggestionsCallback: (pattern) {
    if (pattern.startsWith('@')) {
      final prefix = pattern.substring(1).toLowerCase();
      return fullNames.where((name) => name.toLowerCase().contains(prefix)).toList();
    }
    return [];
  },
  itemBuilder: (context, suggestion) => ListTile(title: Text(suggestion)),
  onSuggestionSelected: (suggestion) {
    final currentText = _controller.text;
    final newText = currentText.substring(0, currentText.lastIndexOf('@')) + '@$suggestion ';
    _controller.text = newText;
    _controller.selection = TextSelection.fromPosition(TextPosition(offset: newText.length));
  },
)

内容的提问来源于stack exchange,提问作者Mubarak Lawal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 13:32:25