Ccc
Ccc

Reputation: 125

Flutter Web - how to prevent web back button to navigate?

How to prevent web back button to navigate?

I have try different routing library( go router, auto route, get, on generated route), but those seems not working to stop back button or my practice is not good.

All I want is, supposed there is a login page, after user login, it will route to home page, in this page, user cannot click browser back button to navigate back just like android back button .

When I try to use go router, the go router navigator stack is not sync as browser stack, when I use go to a page (PageA) from PageB, suppose the PageB is remove, but when i click back button, it still can back to PageB. It is weird

I try to use PopScope to prevent navigate back. But some library didn't work( go router, auto route).

I try to use on generated route, it can prevent the navigation, but the path still change, how to prevent it?

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);
}

Here is auto route example, it cannot be show the PopScope when I click back button. Repo: https://github.com/nepali-programmer/auto_route_integration/tree/auto_route_setup

Add PopScope in ScreenB, the print('!!!') is printed, but the dialog didn't show up, and the page changed.


@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());
              },
            ),
          ],
        ),
      ),
    );
  }
}```

Upvotes: 2

Views: 196

Answers (1)

shotmeinthehead
shotmeinthehead

Reputation: 1301

I think you can't actually prevent users from going back to a page. It will confuse them, also if any error occured within the app, it is not possible to go back (obviously). What you can do tho is handle a case by case scenario. In example, if user is loged in, then when he comes back to the login screen, you can check if users is loged in and display a Text saying "You are loged in" or something like that.

Upvotes: 0

Related Questions