Flutter中如何在不聚焦EditableText/TextField的前提下显示光标/插入符
Flutter 无焦点下控制EditableText内容并显示光标解决方案
核心实现逻辑
- 禁用EditableText自动抢焦点的配置,不抢占Widget1的焦点资源
- 强制开启光标显示配置,无需持有焦点也能正常渲染光标
- 同步外部传入的文本内容和光标位置即可完成需求
具体修改步骤
1. 补全Widget2入参
原代码中使用了emailSelectionOffset但未在构造函数中声明,补充该可选参数,若不需要自定义光标位置可默认使用文本长度让光标固定在内容末尾。
2. 修改EditableText配置
- 移除
autofocus: true配置,避免组件初始化时抢占Widget1的焦点 - 新增
enableInteractiveSelection: true配置,保留下光标渲染能力 - 保留
readOnly: true、showCursor: true原有配置
3. 优化控制器赋值逻辑
将控制器更新逻辑移到didUpdateWidget生命周期中,增加内容变更判断,避免重复build造成的无意义赋值,提升性能。
修改后完整代码
Widget2代码
class Widget2 extends StatefulWidget { final String email; // 可选参数,自定义光标偏移量,不传默认在文本末尾 final int? emailSelectionOffset; const Widget2({ required this.email, this.emailSelectionOffset, }); @override _Widget2State createState() => _Widget2State(); } class _Widget2State extends State<Widget2> { final TextEditingController _email = TextEditingController(); final FocusNode _nodeEmail = FocusNode(); @override void didUpdateWidget(covariant Widget2 oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.email != widget.email) { final targetOffset = widget.emailSelectionOffset ?? widget.email.length; _email.value = _email.value.copyWith( text: widget.email, selection: TextSelection.collapsed(offset: targetOffset), ); } } @override Widget build(BuildContext context) { return EditableText( controller: _email, focusNode: _nodeEmail, cursorColor: Colors.white, backgroundCursorColor: Colors.white, style: TextStyle(color: Colors.white), readOnly: true, showCursor: true, enableInteractiveSelection: true, ); } }
父组件调用调整(可选)
如果需要自定义光标位置,在调用Widget2时传入对应参数即可:
AnimatedBuilder( animation: email, builder: (BuildContext context, _){ return Widget2( email: email.value, // 传入自定义光标偏移量 // emailSelectionOffset: yourCustomOffset, ); } ),
修改完成后Widget1可正常持有焦点,EditableText无需获取焦点即可同步外部更新的内容,同时光标正常显示。
内容的提问来源于stack exchange,提问作者Jackson Lee
相关产品推荐
相关产品推荐

