When typing the mobile back button, the flutter application exits

Viewed 1187

I have a problem, when typing in the mobile back button, my application exists. However when i click in the back button icon, in my AppBar Screen, i navigate to the previous screen, whitch is good.

I would like to know why the mobile back button do not navigate to the previous screen like the AppBar back button icon ?

I have done my test by using this code from https://medium.com/flutterdevs/flutter-migrate-to-navigator-2-0-851f568ac0a3:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  // This widget is the root of your application.
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool isStacked = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Navigator(
        pages: [
          MaterialPage(
            key: ValueKey('unique '),
            child: Screen1(
              onTap: (value) {
                isStacked = value;
                setState(() {});
              },
            ),
          ),
          if (isStacked == true)
            MaterialPage(
              child: Screen2(),
            ),
        ],
        onPopPage: (route, result) {
          if (!route.didPop(result)) return false;
          setState(() => isStacked = false);
          return true;
        },
      ),
    );
  }
}

class Screen1 extends StatelessWidget {
  Function(bool) onTap;

  Screen1({this.onTap});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Navigator 2.0"),
      ),
      body: Center(
        child: InkWell(
          onTap: () {
            onTap(true);
          },
          child: Text(
            'Screen 1 \n tap on text to maove to screen2',
          ),
        ),
      ),
    );
  }
}

class Screen2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Back to Screen 1"),
      ),
      body: Center(
        child: InkWell(
          child: Text(
            'Screen 2 ',
          ),
        ),
      ),
    );
  }
}

I wrap the Navigator widget in WillPopScope widget, but the mobile back button do not work.

Thanks.

2 Answers

You should use a router with a routerDelegate and a backButtonDispatcher.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            home: Router(
                routerDelegate: MyRouterDelegate(),
                backButtonDispatcher: RootBackButtonDispatcher(),
            ),
        );
    }
}

class MyRouterDelegate extends RouterDelegate with ChangeNotifier {

final GlobalKey<NavigatorState> navigatorKey;

MyRouterDelegate() : navigatorKey = GlobalKey<NavigatorState>();

@override
Future<bool> popRoute() async {
    return false; //if true the app will never exit. Otherwise, if you are on the rootpage the app will exit
}

@override
Widget build(BuildContext context) {
    return Navigator(
        key: navigatorKey,
        pages: [
            //HERE'S YOUR PAGE STUFF
        ],
        onPopPage: (route, result) {
            if (!route.didPop(result)) return false;
            notifyListeners(); //seems to be better than setState to manage Navigator
            return true;
        },
    );
}

// We don't use named navigation so we don't use this
@override
Future<void> setNewRoutePath(configuration) async => null;
}

Anyway I followed this medium tutorial (composed of 6 articles to "master" this navigator 2.0), hope it will help you (this is the first of the serie): https://lucasdelsol01.medium.com/flutter-navigator-2-0-101-for-mobile-dev-5094566613f6

Your Navigation method was the problem. since you are using Navigator it just show last widget of the page: . Which means that you always have one screen in the stack. therefore the app is exit when you press back button.

Update your code with this this will solve the problem.

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  // This widget is the root of your application.
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool isStacked = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Screen1(),
    );
  }
}

class Screen1 extends StatelessWidget {
  Screen1();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Navigator 2.0"),
      ),
      body: Center(
        child: InkWell(
          onTap: () {
            Navigator.of(context).push(MaterialPageRoute(builder: (context) => Screen2()));
          },
          child: Text(
            'Screen 1 \n tap on text to maove to screen2',
          ),
        ),
      ),
    );
  }
}

class Screen2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Back to Screen 1"),
      ),
      body: Center(
        child: InkWell(
          child: Text(
            'Screen 2 ',
          ),
        ),
      ),
    );
  }
}

Here when you navigated to second screen. The second screen will be loaded on top of the first screen therefore when you press back button you will be navigated to first page.

Related