Flutter中将Container颜色设为null后CupertinoTextField首次点击无法聚焦如何解决
问题原因
- 点击两次才获取焦点的问题:你给FocusNode绑定了监听回调,当文本框获得焦点时会立即执行setState更新
displayEditor为true。第一次点击文本框时,触摸事件先触发文本框的焦点获取逻辑,触发监听回调执行setState引发整个页面重建,正在传递的触摸事件流被重建过程打断,导致第一次点击无法完成完整的对焦逻辑。第二次点击时displayEditor已经是true,不会触发额外的重建,事件可以正常传递完成对焦。 - 文本框内容看起来被擦除的问题:你在点击DONE按钮的setState回调中,同步执行了
focus.unfocus()和修改displayEditor为false的操作,两个状态变化在同一次组件重建中生效,Flutter渲染流水线处理同步的焦点变化和根容器背景色变化时,CupertinoTextField的绘制出现时序异常,导致内容看起来被清空,实际文本内容并没有丢失。
修复方案
这里提供两种简单的可落地修复方案,任选一种即可:
方案1:调整状态更新时序
将displayEditor的修改延迟到当前帧渲染完成之后,避免焦点变化和背景色变化在同一次重建中生效,修改DONE按钮的onPressed逻辑:
onPressed: () { if (focus.hasFocus) { focus.unfocus(); // 等待当前帧渲染完成后再更新背景色状态 WidgetsBinding.instance.addPostFrameCallback((_) { setState(() { displayEditor = false; }); }); } }
方案2:调整Stack的命中测试行为
给Stack增加hitTestBehavior属性,强制Stack拦截所有自身区域内的点击事件,避免事件传递异常:
Stack( // 新增此行配置 hitTestBehavior: HitTestBehavior.opaque, children: [ // 原有子组件代码保持不变 ], )
如果想要更好的性能,也可以把根Container单独拆分为独立的Stateful组件,用局部重建代替全页面重建,从根源避免触摸事件被重建打断的问题。
内容的提问来源于stack exchange,提问作者nicover
相关产品推荐
相关产品推荐

