You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 04:23:14