Flutter动态新增TextField真机无法自动获焦该如何解决?
问题成因
autofocus属性仅在页面首次渲染阶段会被Flutter框架扫描生效,动态新增组件时,原生端不会二次触发autofocus的匹配逻辑,而DartPad为Web环境,底层输入框实现和原生端差异较大,所以出现了两端表现不一致的情况。- 调用
setState新增控制器后,新的TextField需要一帧的时间才能完成渲染挂载,未挂载完成时直接触发聚焦逻辑也会失效。
解决方案
配合FocusNode监听渲染生命周期,等新增TextField挂载完成后主动触发聚焦即可,修改后的代码如下:
class _TestPageState extends State<TestPage> { List<TextEditingController> controllers = [ TextEditingController(text: 'field 0') ]; // 存储每个TextField对应的焦点节点 List<FocusNode> focusNodes = [FocusNode()]; @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: ListView.builder( itemCount: controllers.length, itemBuilder: (context, index) => TextField( controller: controllers[index], focusNode: focusNodes[index], )), ), floatingActionButton: FloatingActionButton( child: const Icon(Icons.add), onPressed: () { // 提前创建新的控制器和焦点节点 final newController = TextEditingController(text: 'field ${controllers.length}'); final newFocusNode = FocusNode(); setState(() { controllers.add(newController); focusNodes.add(newFocusNode); }); // 等待当前帧渲染完成,组件挂载后再请求聚焦 WidgetsBinding.instance.addPostFrameCallback((_) { newFocusNode.requestFocus(); }); }, ), ); } @override void dispose() { // 销毁所有控制器和焦点节点,避免内存泄漏 for (var controller in controllers) { controller.dispose(); } for (var node in focusNodes) { node.dispose(); } super.dispose(); } }
注意事项
- 不要依赖
autofocus处理动态新增组件的聚焦逻辑,它的设计适用场景仅为页面初始化时的单个组件自动聚焦 - 如果新增的TextField位于滚动视图可视区域外,可在请求聚焦后补充滚动逻辑,让输入框滚动到可视区域内
内容的提问来源于stack exchange,提问作者Andriy Trubchanin
相关产品推荐
相关产品推荐

