Flutter WebView结合GoRouter(Navigation 2.0):如何处理返回键点击
在Navigator 2.0(如GoRouter)环境下,旧的WillPopScope不再生效,默认返回键会直接触发当前路由弹出,导致WebView内的页面回退需求被忽略——用户在WebView跳转后点返回键,会直接回到上一个Flutter页面,而不是WebView的上一页。
以下是两种可行的解决方案:
方案一:使用PopScope(Flutter 3.10+ 推荐)
PopScope是Flutter官方推出的替代WillPopScope的组件,完美适配Navigator 2.0生态。在包含WebView的页面中嵌套PopScope,自定义返回键逻辑:
class WebViewPage extends StatefulWidget { final String url; const WebViewPage({super.key, required this.url}); @override State<WebViewPage> createState() => _WebViewPageState(); } class _WebViewPageState extends State<WebViewPage> { late final WebViewController _webController; @override void initState() { super.initState(); _webController = WebViewController() ..loadRequest(Uri.parse(widget.url)) ..setNavigationDelegate(NavigationDelegate( onPageFinished: (_) => setState(() {}), )); } @override Widget build(BuildContext context) { return PopScope( // 阻止默认路由弹出行为 canPop: false, onPopInvoked: (bool didPop) async { // 优先检查WebView是否可回退 if (await _webController.canGoBack()) { _webController.goBack(); } else { // WebView无历史页面时,再退出当前路由 if (context.mounted) { context.pop(); } } }, child: Scaffold( appBar: AppBar(title: const Text("网页")), body: WebViewWidget(controller: _webController), ), ); } }
逻辑说明:
- 设置
canPop: false禁用默认的路由弹出,将返回键逻辑完全交由onPopInvoked处理。 - 在
onPopInvoked中先调用_webController.canGoBack()判断WebView是否有历史页面:- 有历史页面则执行
_webController.goBack()让WebView回退。 - 无历史页面时,再调用
context.pop()退出当前Flutter路由。
- 有历史页面则执行
方案二:利用GoRouter的onExit回调
如果需要在路由层面统一处理,可以在GoRouter的路由配置中添加onExit回调:
final GoRouter _router = GoRouter( routes: [ GoRoute( path: '/webview', builder: (context, state) => WebViewPage( url: state.queryParameters['url']!, ), onExit: (context) async { final webPageState = context.findAncestorStateOfType<_WebViewPageState>(); if (webPageState != null && await webPageState._webController.canGoBack()) { webPageState._webController.goBack(); // 返回false阻止路由退出 return false; } // 返回true允许路由退出 return true; }, ), ], );
注意事项:
- 需要确保能获取到WebViewController的实例,可通过
GlobalKey或状态管理(如Provider)实现。 - 该方案适合需要在路由全局层面控制返回行为的场景,灵活性不如页面内的
PopScope。
内容的提问来源于stack exchange,提问作者Delmontee
相关产品推荐
相关产品推荐

