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

Flutter中如何避免EditableText光标失去焦点后跳至字符串末尾

问题:自定义按钮输入时EditableText光标跳至末尾

场景与代码

在Flutter应用中使用EditableText组件并禁用键盘输入,通过两个TextButton点击来修改绑定的TextEditingController文本内容:

EditableText代码

EditableText(
  keyboardType: TextInputType.none,
  autofocus: true,
  controller: _queryCtl,
  cursorColor: Colors.white,
  backgroundCursorColor: Colors.black,
  focusNode: tN,
  onTapOutside: (event) {
    print("tapped outside");
  },
  style: const TextStyle(
    fontSize: 32,
    color: Color.fromARGB(255, 219, 175, 42),
  ),
)

自定义按钮代码

Row(
  children: [
    TextButton(
      onPressed: () {
        addChar("2");
      },
      child: const Text('Add 2'),
    ),
    TextButton(
      onPressed: () {
        addChar("3");
      },
      child: const Text('Add 3'),
    ),
  ],
)

问题现象

  1. 将光标放置在EditableText的字符串中间位置
  2. 首次点击TextButton,字符会插入到光标位置(符合预期)
  3. 再次点击TextButton,字符直接插入到字符串末尾(不符合预期)

解决方案

问题根源在于直接修改TextEditingController的text属性时,会自动重置光标位置到文本末尾。正确的做法是通过TextEditingValue同时更新文本和光标选中状态:

修改addChar方法如下:

void addChar(String char) {
  final currentValue = _queryCtl.value;
  final selection = currentValue.selection;
  
  // 构建新文本:在光标选中区域插入字符
  final newText = currentValue.text.replaceRange(
    selection.start,
    selection.end,
    char,
  );
  
  // 计算新的光标位置:插入位置 + 字符长度
  final newSelection = selection.copyWith(
    baseOffset: selection.start + char.length,
    extentOffset: selection.start + char.length,
  );
  
  // 更新controller的完整值,保留光标状态
  _queryCtl.value = TextEditingValue(
    text: newText,
    selection: newSelection,
    composing: TextRange.empty,
  );
}

说明

  • 避免直接使用_queryCtl.text = ...或_queryCtl.text += ...这类方式修改文本,这类操作会丢失当前的光标选中状态
  • 通过TextEditingValue同时设置text和selection,可以确保光标始终停留在插入后的位置,模拟原生键盘的输入行为

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 00:15:19