This is main.dart

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
    ]);

    return MaterialApp(
        title: 'List',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          primarySwatch: Colors.green,
        ),
        home: HomeScreen());
  }
}

This is homescreen.dart

class HomeScreen extends StatefulWidget {
  HomeScreen({Key key}) : super(key: key);

  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {

  int _currentindex = 0;
  final List<Widget> screen = [
    DashboardNavigator(),
    RegisterPage(),
  ];

  Future<bool> _onBackPressed() {
  return showDialog(
    context: context,
    builder: (context) => new AlertDialog(
      title: new Text('Are you sure ?'),
      content: new Text('Do you want to exit ?'),
      actionsPadding: EdgeInsets.only(right:10.0,bottom:10.0),
      actions: <Widget>[
        new GestureDetector(
          onTap: () => Navigator.of(context).pop(false),
          child: Text("No",
          style:TextStyle(
            color:Colors.red
          )),
        ),
        SizedBox(height: 16),
        new GestureDetector(
          onTap: () => Navigator.of(context).pop(true),
          child: Text("Yes",
          style:TextStyle(
            color:Colors.green
          )),
        ),
      ],
    ),
  ) ??
      false;
}

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
    onWillPop:_onBackPressed,
    child:Scaffold(
          body: SafeArea(
            child: IndexedStack(
              index:_currentindex,
              children: screen,
            )
            ),
            bottomNavigationBar: BottomNavigationBar(
            currentIndex: _currentindex,
            onTap: (int index) {
              this.setState(() {
                _currentindex = index;
                }
              );
            },
            items:[
              BottomNavigationBarItem(icon: Icon(Icons.home,color:Colors.green),title:Text('Home')),
              BottomNavigationBarItem(icon: Icon(Icons.settings_ethernet,color:Colors.green),title:Text('Console')),
            ]
          )
    ));
  }
}

This is the Navigator Widget

class DashboardNavigator extends StatefulWidget {
  DashboardNavigator({Key key}) : super(key: key);

  @override
  _DashboardNavigatorState createState() => _DashboardNavigatorState();
}

class _DashboardNavigatorState extends State<DashboardNavigator> {

  String url;

  @override
  Widget build(BuildContext context) {
    return Navigator(
      onGenerateRoute: (RouteSettings settings) {
        return MaterialPageRoute(
          settings: settings,
          builder: (BuildContext context) {
            switch(settings.name) {
              case '/':
                return DashBoard();
              case '/listhub':
                return ListHub();
              case '/listhub/listfarmer':
                return ListFarmer(url);
            }
          },
        );
      }
    );
  }
}

I used Navigator.pushNamed function to navigate between these screen

onPressed: () => Navigator.pushNamed(context,"/listhub"),

but when i click on the android back button it closes the app instead of navigating to the previous page ... I tried WillpopScope in each page but it doesn't work.

Please Suggest me the correct way to navigate back to the previous screen using android back button and also appBar back button.


Solution 1: caseycrogers

I believe this is happening because you're pushing to your own Navigator while the OS level back gesture and your _onBackPressed function are popping from MaterialApp's navigator. Since the latter hasn't had any routes pushed it, it behaves as expected and exits the app.

This Github issue covers the problem in detail with a couple different solutions. You could create a global key in main and pass it to materialApp using the navigatorKey argument and to DashboardNavigator using its key argument. This way, both MaterialApp and your DashboardNavigator will use the same navigator wherever you push or pop.


Solution 2: dev-jim

This is how I make it works by referring this:

class _MyAppState extends State<MyApp> {
  final _navigatorKey = GlobalKey<NavigatorState>();//define a navigation key.

  @override
  Widget build(BuildContext context) {
     return MaterialApp(
        title: 'My APP',
        navigatorKey: _navigatorKey,//this is the navigation key
        onGenerateRoute: (_) => null,
        builder: (context, child) {
            return Navigator(
                key: _navigatorKey,//same navigation key
                pages: [
                    MaterialPage(
                      key: const ValueKey('homepage'),
                      child: HomPage(),//homepage widget
                     ....
                ],
                onPopPage: (route, result) {
                   //pop logic here. 
                }
            );
        }
     );
  }
}

The discussion here also mention using WillPopScope wrapper, maybe you can try this as well.