I want to leverage nested routes in Flutter. I think I managed what I wanted apart from one thing. My nested "home" route does not show back navigation in AppBar
, however hardware button will get me to previous route. Perhaps I'm not using nested routes correctly.
I have a root MaterialApp
that defines main root pages via routes
property. One of root pages is MyChildPage
that renders another Navigator
and uses onGenerateRoute
property to point user to its child pages. Navigation works but when I land on MyChildPage
(it has title "Child page"), the back button is missing:
Code
You can run interactive example on dartpad.dev where the code is also visible.
I have everything in single file:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Nested tutorial',
theme: ThemeData(
primarySwatch: Colors.orange,
),
initialRoute: '/',
routes: {
'/': (_) => MyHomePage(),
'/sub_page': (_) => MySubPage(),
'/child': (_) => MyChildPage(),
});
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Hello this is home page'),
ElevatedButton(
child: Text('Visit sub page'),
onPressed: () {
Navigator.pushNamed(context, '/sub_page');
}),
OutlinedButton(
child: Text('Visit child page'),
onPressed: () {
Navigator.pushNamed(context, '/child');
}),
],
),
),
);
}
}
class MySubPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home / Sub Page')),
body: Center(child: Text('Hello this is sub page')),
);
}
}
class MyChildPage extends StatefulWidget {
@override
_MyChildPageState createState() => _MyChildPageState();
}
class _MyChildPageState extends State<MyChildPage> {
@override
Widget build(BuildContext context) {
return Navigator(
initialRoute: '/',
onGenerateRoute: (settings) {
switch (settings.name) {
case '/child_1':
return MaterialPageRoute(builder: (_) => MyChildPage1());
case '/child_2':
return MaterialPageRoute(builder: (_) => MyChildPage2());
case '/':
default:
return MaterialPageRoute(builder: (_) => MyChildPageRoot());
}
});
}
}
class MyChildPageRoot extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Child page')),
body: Container(
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Center(child: Text('This is child page root ')),
Center(
child: OutlinedButton(
child: Text('Visit sub child page 1'),
onPressed: () {
Navigator.pushNamed(context, '/child_1');
})),
Center(
child: OutlinedButton(
child: Text('Visit sub child page 2'),
onPressed: () {
Navigator.pushNamed(context, '/child_2');
})),
])),
);
}
}
class MyChildPage1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Child sub page 1')),
body: Center(child: Text('You are on child sub page #1')),
);
}
}
class MyChildPage2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Child sub page 2')),
body: Center(child: Text('You are on child sub page #2')),
);
}
}
I am looking for a solution where I can still use named routes and I want to keep structure of multiple Navigators. I do not want to define all routes in my top-level MaterialApp
widget.