如何在Flutter页面跳转时保持键盘显示且EditText不失去焦点
问题概述
现有Widget结构如下:
- home (stack of widgets) - page container - editText field
editText固定在Stack最上层,通过Navigator.of(context)切换page container内的页面;当前跳转页面时editText会自动失去焦点、键盘收起,需要实现跳转时保持editText聚焦、键盘持续显示。
根因说明
Flutter执行Navigator路由切换时,默认会对旧路由的焦点树执行清理操作,全局焦点被回收,导致Stack上层独立的editText也会丢失焦点,触发键盘收起。
可行实现方案
方案1:绑定全局FocusNode,路由变动后强制请求焦点(推荐优先使用,改造成本最低)
给editText绑定一个全局生命周期的FocusNode实例,同时给page container内的Navigator添加路由观察者,路由跳转完成后自动触发焦点请求,示例代码如下:- 定义FocusNode并绑定到
editText
// 全局持有FocusNode,生命周期和home页面一致 final _editTextFocusNode = FocusNode(); // 绑定到editText组件 TextField( focusNode: _editTextFocusNode, // 其余属性省略 )- 自定义路由观察者监听路由变动
class KeepEditTextFocusObserver extends NavigatorObserver { final FocusNode targetFocusNode; KeepEditTextFocusObserver(this.targetFocusNode); @override void didPush(Route route, Route? previousRoute) { super.didPush(route, previousRoute); _requestFocusAfterFrame(); } @override void didPop(Route route, Route? previousRoute) { super.didPop(route, previousRoute); _requestFocusAfterFrame(); } @override void didReplace({Route? newRoute, Route? oldRoute}) { super.didReplace(newRoute: newRoute, oldRoute: oldRoute); _requestFocusAfterFrame(); } void _requestFocusAfterFrame() { WidgetsBinding.instance.addPostFrameCallback((_) { if(!targetFocusNode.hasFocus) { targetFocusNode.requestFocus(); } }); } }- 将观察者传入page container内的Navigator配置
Navigator( observers: [KeepEditTextFocusObserver(_editTextFocusNode)], // 其余配置省略 )- 定义FocusNode并绑定到
方案2:隔离焦点作用域
将page container的整个子树用FocusScope组件包裹,设置独立的焦点范围,路由切换时只会在该子树内处理焦点逻辑,不会影响上层editText的焦点状态:FocusScope( canRequestFocus: true, debugLabel: 'PageContainerFocusScope', child: Navigator( // page container的Navigator配置 ), )方案3:修改路由默认焦点逻辑
如果使用自定义路由实现,可以重写路由的焦点处理回调,禁止路由切换时回收全局焦点;如果使用默认的MaterialPageRoute,确认maintainState参数为true(默认值即为true,无需额外修改),同时检查自定义页面转场动画中是否包含主动调用unfocus()的逻辑,如有直接删除即可。
注意事项
- 焦点请求逻辑必须放在
WidgetsBinding.instance.addPostFrameCallback回调中执行,避免在页面渲染过程中修改焦点状态触发布局异常 FocusNode使用完成后需要调用dispose()方法释放,避免内存泄漏- Android端如果出现跳转时键盘闪动,可以将对应Activity的
windowSoftInputMode配置为adjustResize,避免布局变动导致键盘被强制收起
内容的提问来源于stack exchange,提问作者Andriy Antonov
相关产品推荐
相关产品推荐

