Our app is built on top of Scaffold
and to this point we have been able to accommodate most of our routing and navigation requirements using the provided calls within NavigatorState
(pushNamed()
, pushReplacementNamed()
, etc.). What we don't want though, is to have any kind of 'push' animation when a user selects an item from our drawer (nav) menu. We want the destination screen from a nav menu click to effectively become the new initial route of the stack. For the moment we are using pushReplacementNamed() for this to ensure no back arrow in the app bar. But, the slide-in-from-the-right animation implies a stack is building.
What is our best option for changing that initial route without animation, and, can we do that while also concurrently animating the drawer closed? Or are we looking at a situation here where we need to move away from Navigator over to just using a single Scaffold and updating the 'body' directly when the user wants to change screens?
We note there is a replace()
call on NavigatorState
which we assume might be the right place to start looking, but it's unclear how to access our various routes originally set up in new MaterialApp()
. Something like replaceNamed()
might be in order ;-)
With Navigator 2.0, there are two ways: Rebuild the Navigator with a new pages list that has the last item replaced. If the previous Page and replacement Page both have no key or the same key, then Flutter will treat them as the same page and will not animate.
There is no way to disable Transition animations and Slide Animations on FLutter, but this a requested feature right now due to Flutter Web being a thing now. As a workaround, you can use the transition-duration property of PageRouteBuilder Widget. Navigator.
What you're doing sounds somewhat like a BottomNavigationBar
, so you might want to consider one of those instead of a Drawer
.
However, having a single Scaffold
and updating the body
when the user taps a drawer item is a totally reasonable approach. You might consider a FadeTransition
to change from one body to another.
Or, if you like using Navigator
but don't want the default slide animation, you can customize (or disable) the animation by extending MaterialPageRoute
. Here's an example of that:
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyCustomRoute<T> extends MaterialPageRoute<T> {
MyCustomRoute({ WidgetBuilder builder, RouteSettings settings })
: super(builder: builder, settings: settings);
@override
Widget buildTransitions(BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
if (settings.isInitialRoute)
return child;
// Fades between routes. (If you don't want any animation,
// just return child.)
return new FadeTransition(opacity: animation, child: child);
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Navigation example',
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/': return new MyCustomRoute(
builder: (_) => new MyHomePage(),
settings: settings,
);
case '/somewhere': return new MyCustomRoute(
builder: (_) => new Somewhere(),
settings: settings,
);
}
assert(false);
}
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Navigation example'),
),
drawer: new Drawer(
child: new ListView(
children: <Widget> [
new DrawerHeader(
child: new Container(
child: const Text('This is a header'),
),
),
new ListTile(
leading: const Icon(Icons.navigate_next),
title: const Text('Navigate somewhere'),
onTap: () {
Navigator.pushNamed(context, '/somewhere');
},
),
],
),
),
body: new Center(
child: new Text(
'This is a home page.',
),
),
);
}
}
class Somewhere extends StatelessWidget {
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Text(
'Congrats, you did it.',
),
),
appBar: new AppBar(
title: new Text('Somewhere'),
),
drawer: new Drawer(
child: new ListView(
children: <Widget>[
new DrawerHeader(
child: new Container(
child: const Text('This is a header'),
),
),
],
),
),
);
}
}
Use PageRouteBuilder
like:
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (_, __, ___) => Screen2(),
transitionDuration: Duration.zero,
),
);
And if you want transition, simply add following property to above PageRouteBuilder
, and change seconds
to say 1
.
transitionsBuilder: (_, a, __, c) => FadeTransition(opacity: a, child: c),
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