How can I push a widget in the frame of another widget? For example I have a Column with 2 Containers where every Container takes half of the screen. I'd like to make a navigation e.g. only in the bottom container. The same logic as in iOS when the container view has it's own UINavigationController.
As I understood MaterialPageRoute can push widgets only to fullscreen and there aren't any other Route classes, except abstract ones. Maybe I should make my own subclass of ModalRoute/TransitionRoute?
You can use Navigator as a child for the specific part you want to make that. And I used WillPopScope to go back to the previous screen if there is one. and make sure to use GlobalKey() to separate each navigator and give it a unique key. My code :
var keyOne = GlobalKey<NavigatorState>();
var keyTwo = GlobalKey<NavigatorState>();
return Column(
children: [
Expanded(
child: Container(
child: WillPopScope(
onWillPop: () async => !await keyOne.currentState.maybePop(),
child: Navigator(
key: keyOne,
onGenerateRoute: (routeSettings) {
return MaterialPageRoute(
builder: (context) => ScreenOne(),
);
},
),
),
),
),
Expanded(
child: Container(
child: WillPopScope(
onWillPop: () async => !await keyTwo.currentState.maybePop(),
child: Navigator(
key: keyTwo,
onGenerateRoute: (routeSettings) {
return MaterialPageRoute(
builder: (context) => ScreenTwo(),
);
},
),
),
),
),
],
);
You can use the Navigator widget to provide any number of individual navigators in your app. Each Navigator will maintain it's own navigation stack. For example, if you wanted to split your app vertically with each half having it's own navigation stack:
Column(
children: <Widget>[
Navigator(...),
Navigator(...)
]
)
If you do this, you should consider how you want to handle the Android back button (now that you technically have 3 navigators in your app). By default, it will only listen to your root navigator so you will have to provide a WillPopScope widget somewhere in your widget hierarchy to capture back button events and pop from the appropriate navigator.
One possible solution would be to create a new MaterialApp on that portion of the screen and handle everything from there like a regular app (just with different screen size) like so:
Column(
children: <Widget>[
Container(
height: constraints.maxHeight * 0.5,
width: constraints.maxWidth,
),
Container(
height: constraints.maxHeight * 0.5,
width: constraints.maxWidth,
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Color.fromRGBO(86, 86, 86, 1.00),
),
initialRoute: '/W1',
routes: {
'/W1': (context) => WidgetOne(),
'/W2': (context) => WidgetTwo(),
})),
],
),
Then handle the routing from withing the widgets like so:
class WidgetOne extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.pushNamed(context, '/W2');
},
child: Container(color: Colors.green));
}
}
}
class WidgetTwo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.pushNamed(context, '/W1');
},
child: Container(color: Colors.pink));
}
}
}
Result: https://i.stack.imgur.com/qyJ5N.gif
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With