Flutter Web如何阻止浏览器返回按钮跳转?
Flutter Web 阻止浏览器返回按钮跳转问题
我需要实现Flutter Web中阻止浏览器返回按钮跳转的功能:例如用户登录后进入主页,无法通过返回按钮回到登录页。尝试了go router、auto route、get、onGenerateRoute等多种路由库,但均未成功或存在使用问题:
- 使用go router时,路由栈与浏览器栈不同步,调用
go方法跳转后仍可返回上一页; - 使用
PopScope组件在go router、auto route中失效:如在auto route的ScreenB中添加PopScope,仅打印日志但弹窗不显示,页面仍跳转; - 使用
onGenerateRoute可阻止导航,但浏览器路径仍会变化。
原生路由(onGenerateRoute)代码示例
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const MyHomePage(), onGenerateRoute: (RouteSettings settings) => AppRoutes.getRoute( settings, // observer: observer, ), ); } } class MyHomePage extends StatefulWidget { const MyHomePage(); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'My Home', ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () { Navigator.pushNamed(context, '/one'); // Navigator.push( // context, // MaterialPageRoute( // builder: (context) => One(), // settings: RouteSettings(name: "one"), // ), // ); }, tooltip: 'Increment', child: const Icon(Icons.add), ), ); } } class One extends StatefulWidget { @override State<One> createState() => _OneState(); } class _OneState extends State<One> { @override Widget build(BuildContext context) { return PopScope( canPop: false, onPopInvoked: (didPop) { if (didPop) { return; } showDialog( context: context, builder: (BuildContext context) { return Scaffold( body: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text('can not pop'), ElevatedButton( onPressed: () { Navigator.of(context).pop(); }, child: Text('OK'), ), ], ), ); }); }, child: Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'One', ), ElevatedButton( onPressed: () { Navigator.of(context).pop(); }, child: Text('OK'), ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () {}, tooltip: 'Increment', child: const Icon(Icons.add), ), ), ); } } class AppRoutes { static const one = "/one"; static const two = "/two"; static const login = "/login"; static const home = "/home"; static MaterialPageRoute getRoute(RouteSettings settings) { switch (settings.name) { case AppRoutes.one: return MainRoute(One(), settings: settings); default: return MainRoute(MyHomePage(), settings: settings); } } } class MainRoute<T> extends MaterialPageRoute<T> { MainRoute( Widget widget, { RouteSettings? settings, }) : super(builder: (_) => widget, settings: settings); }
Auto Route代码示例
在ScreenB中添加PopScope后,仅打印日志但弹窗不显示,页面仍跳转:
@RoutePage() class ScreenB extends StatelessWidget { const ScreenB({super.key}); @override Widget build(BuildContext context) { return PopScope( canPop: false, onPopInvoked: (didPop) { print('!!!!!!!!!!!!!!!!'); print(didPop); if (didPop) { return; } showDialog( context: context, builder: (BuildContext context) { return Scaffold( body: Column( children: [ Text('can not pop'), ElevatedButton( onPressed: () { Navigator.of(context).pop(); }, child: Text('OK'), ), ], ), ); }); }, child: Scaffold( appBar: AppBar(), backgroundColor: Colors.blue, body: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ ElevatedButton( child: const Text('Goto Screen c'), onPressed: () { context.router.push(const RouteC()); }, ), ], ), ), ); } }
内容的提问来源于stack exchange,提问作者Ccc
相关产品推荐
相关产品推荐

