这是一个非常典型、而且你现在已经走到「架构层」的问题 👍你问的是:
如何统一、全局地实现:页面返回(pop)时自动 unfocus(取消光标 & 键盘)
答案是:👉 用 NavigatorObserver / RouteObserver 在路由层统一处理而不是在每个页面、每个 TextField 手动写。
NavigatorObserver / RouteObserver
下面我给你 3 种方案,从“最推荐”到“兜底”,并告诉你为什么选它。
NavigatorObserver
只要发生 pop(返回),统一调用:
FocusManager.instance.primaryFocus?.unfocus();
class UnfocusOnPopObserver extends NavigatorObserver { void _unfocus() { FocusManager.instance.primaryFocus?.unfocus(); } @override void didPop(Route route, Route? previousRoute) { _unfocus(); super.didPop(route, previousRoute); } @override void didPush(Route route, Route? previousRoute) { // 可选:push 时也 unfocus(防止闪键盘) _unfocus(); super.didPush(route, previousRoute); } @override void didReplace({Route? newRoute, Route? oldRoute}) { _unfocus(); super.didReplace(newRoute: newRoute, oldRoute: oldRoute); } }
MaterialApp
MaterialApp( navigatorObservers: [ UnfocusOnPopObserver(), ], home: const HomePage(), );
Navigator.push / pop / replace
TestHome
完全不用改你写的任何页面代码
👉 键盘是全局 UI 状态,就应该在路由层处理
如果你希望:
didPopNext
final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
注册:
MaterialApp( navigatorObservers: [routeObserver], );
class _HomeState extends State<Home> with RouteAware { @override void didChangeDependencies() { super.didChangeDependencies(); routeObserver.subscribe( this, ModalRoute.of(context)! as PageRoute, ); } @override void didPopNext() { FocusManager.instance.primaryFocus?.unfocus(); } @override void dispose() { routeObserver.unsubscribe(this); super.dispose(); } }
📌 适合:
但不如方案一简单统一
WidgetsBindingObserver
class GlobalUnfocusObserver with WidgetsBindingObserver { @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { FocusManager.instance.primaryFocus?.unfocus(); } } }
📌 只能处理:
⚠️ 不推荐作为主方案
你原来的代码:
await Navigator.of(context).push( MaterialPageRoute(builder: (_) => TestHome()), );
👉 完全不用改
只要在 MaterialApp 里加:
navigatorObservers: [ UnfocusOnPopObserver(), ],
你现在的行为会变成:
键盘 / Focus 是全局状态路由切换是全局事件👉 用 NavigatorObserver 统一处理
我可以帮你:
AppNavigatorObserver
直接告诉我你用的是哪套路由(Navigator 1.0 / GoRouter)即可。
Github开源生信云平台 DEMO