NavigatorObserver(最干净)
WidgetsBindingObserver这是一个非常典型、而且你现在已经走到「架构层」的问题 👍
你问的是:
如何统一、全局地实现:页面返回(pop)时自动 unfocus(取消光标 & 键盘)
答案是:
👉 用 NavigatorObserver / RouteObserver 在路由层统一处理
而不是在每个页面、每个 TextField 手动写。
下面我给你 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 / replaceTestHome完全不用改你写的任何页面代码
| 方式 | 是否推荐 | 原因 |
|---|---|---|
| push 前手动 unfocus | ❌ | 容易忘 |
| 每个页面 dispose | ❌ | 太分散 |
| WillPopScope | ⚠️ | 只能处理 back |
| NavigatorObserver | ✅✅✅ | 路由层统一处理 |
👉 键盘是全局 UI 状态,就应该在路由层处理
如果你希望:
didPopNext(返回到该页面)时 unfocusfinal 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();
}
}
📌 适合:
但不如方案一简单统一
WidgetsBindingObserverclass 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)即可。