如何获取TextFormField当前光标位置(优先使用TextEditingController)
任意位置@用户标记功能实现方法
你没有遗漏API,TextEditingController自带光标位置获取能力,直接基于光标位置向前匹配@标记即可,不需要额外依赖,完全可以覆盖你提到的三个需求。
核心逻辑步骤
- 第一步:获取当前光标位置
直接读取控制器的selection属性就能拿到光标的文本偏移量,做个基础容错避免无效状态:// 读取光标位置,未聚焦输入框时偏移量为-1,直接终止逻辑 final cursorOffset = controller.selection.baseOffset; if (cursorOffset < 0) { hideMentionPanel(); return; } - 第二步:从光标位置向前遍历匹配有效@标记
从光标前一位开始逐字符向前扫描,遇到空格、换行就终止(说明当前位置前没有紧邻的@标记),遇到@就截取@到光标之间的内容作为搜索关键词:final currentText = controller.text; int scanPointer = cursorOffset - 1; int mentionStartPos = -1; String? searchKey; while (scanPointer >= 0) { final currentChar = currentText[scanPointer]; // 遇到分隔符说明不存在有效的@输入上下文 if (currentChar == ' ' || currentChar == '\n') break; // 匹配到@符号,提取搜索词 if (currentChar == '@') { mentionStartPos = scanPointer; searchKey = currentText.substring(scanPointer + 1, cursorOffset); break; } scanPointer--; } // 搜索词长度≥1时才拉取匹配用户、展示建议面板,符合输入@后打1个以上字符触发的要求 if (searchKey != null && searchKey.isNotEmpty) { final matchedUsers = userList.where((user) => user.username.startsWith(searchKey)).toList(); showMentionPanel(matchedUsers, mentionStartPos, cursorOffset); } else { hideMentionPanel(); } - 第三步:选中用户后的文本替换(支持任意位置插入、多用户标记)
选中要@的用户时,直接替换mentionStartPos到原光标位置的片段为格式化后的标记文本,再把光标移到插入内容末尾即可,不会影响文本其他位置已经输入的内容、已经标记的其他用户:void insertMention(User target) { final originText = controller.text; final insertContent = '@${target.username} '; final updatedText = originText.replaceRange(mentionStartPos, cursorOffset, insertContent); controller.value = controller.value.copyWith( text: updatedText, selection: TextSelection.collapsed( offset: mentionStartPos + insertContent.length ), ); hideMentionPanel(); }
监听绑定
给TextEditingController添加监听,每次文本变化、光标移动时都重新执行上述匹配逻辑即可,不需要额外处理输入位置,不管光标在文本开头、中间、末尾都能正常触发,也支持同时标记多个用户。
小提示:如果需要支持@后面的内容删除后自动重新唤起匹配面板,不需要加额外判断,上述遍历逻辑会自动在内容变化时重新计算搜索词,自动控制面板的显隐。
内容的提问来源于stack exchange,提问作者Rohit Kokate
相关产品推荐
相关产品推荐

