How to navigate to other page without animation Flutter
NavigationFlutterNavigation Problem Overview
I have a Login page, when I log on to go to the main page of my app i am using
Navigator.pushReplacement(context, new MaterialPageRoute(builder: (BuildContext context) => new Page1()));
But it have the slide animation, i want to disable it.
this is my Material app format
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Login(title: 'Login'),
routes: <String, WidgetBuilder>{
'/screen3': (BuildContext context) => new Page1(),
},
);
}
}
Navigation Solutions
Solution 1 - Navigation
You can use PageRouteBuilder
.
Navigator.pushReplacement(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => Page1(),
transitionDuration: Duration.zero,
reverseTransitionDuration: Duration.zero,
),
);
Solution 2 - Navigation
You would need to override the buildTransitions
method to prevent animations.
import 'package:flutter/material.dart';
class NoAnimationMaterialPageRoute<T> extends MaterialPageRoute<T> {
NoAnimationMaterialPageRoute({
@required WidgetBuilder builder,
RouteSettings settings,
bool maintainState = true,
bool fullscreenDialog = false,
}) : super(
builder: builder,
maintainState: maintainState,
settings: settings,
fullscreenDialog: fullscreenDialog);
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return child;
}
}
For Null safety:
import 'package:flutter/material.dart';
class NoAnimationMaterialPageRoute<T> extends MaterialPageRoute<T> {
NoAnimationMaterialPageRoute({
required WidgetBuilder builder,
RouteSettings? settings,
bool maintainState = true,
bool fullscreenDialog = false,
}) : super(
builder: builder,
maintainState: maintainState,
settings: settings,
fullscreenDialog: fullscreenDialog);
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return child;
}
}
Solution 3 - Navigation
You can override MaterialPageRoute
to set transitionDuration
to zero:
class CustomPageRoute extends MaterialPageRoute {
CustomPageRoute({builder}) : super(builder: builder);
@override
Duration get transitionDuration => const Duration(milliseconds: 0);
}
...
Navigator.of(context).push(
CustomPageRoute(
builder: (BuildContext context) {
return DashboardView();
},
),
);
Solution 4 - Navigation
Make sure you also set transitionDuration
otherwise you may push the new route without animation but when you press back button, you'll see some delay.
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (_, __, ___) => Screen2(),
transitionDuration: const Duration(seconds: 0),
),
);
Solution 5 - Navigation
My solution is to define the route with isInitialRoute:true
. This prevents Flutter from showing an animation when the route is pushed.
Here's a working example and screen recording:
import 'package:flutter/cupertino.dart'
show
CupertinoApp,
CupertinoButton,
CupertinoPageRoute,
CupertinoPageScaffold;
import 'package:flutter/widgets.dart'
show
BuildContext,
Center,
Column,
Navigator,
Route,
RouteSettings,
SafeArea,
Spacer,
Text,
runApp,
Widget;
Widget makeButton(BuildContext context, String routeName) =>
new CupertinoButton(
onPressed: () => Navigator.pushReplacementNamed(context, routeName),
child: Text('Go to \'$routeName\''),
);
Route generateRoute(RouteSettings settings) {
switch (settings.name) {
case 'not-animated':
return new CupertinoPageRoute(
settings: RouteSettings(name: settings.name, isInitialRoute: true),
builder: (context) => CupertinoPageScaffold(
child: SafeArea(
child: Center(
child: Column(
children: [
Spacer(),
Text('This is \'not-animated\''),
makeButton(context, 'animated'),
Spacer(),
],
),
),
),
),
);
default:
return null;
}
}
void main() {
runApp(
CupertinoApp(
onGenerateRoute: generateRoute,
initialRoute: 'animated',
routes: {
'animated': (context) => CupertinoPageScaffold(
child: SafeArea(
child: Center(
child: Column(
children: [
Spacer(),
Text('This is \'animated\''),
makeButton(context, 'not-animated'),
Spacer(),
],
),
),
),
),
},
),
);
}
Solution 6 - Navigation
You should try to extend MaterialPageRoute and override buildTransitions as follows:
class ExPageRoute<T> extends MaterialPageRoute<T> {
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return child;
}
}
Solution 7 - Navigation
In case you would like to use a package, with the get package you can disable transition animations with a property of GetMaterialApp
.
GetMaterialApp(
defaultTransition: Transition.noTransition, //this would be the solution
transitionDuration: transitionDuration: Duration(seconds: 0),
);
And then just simply add the other desired properties.
Solution 8 - Navigation
With Navigator 2.0, there are two ways:
- Rebuild the Navigator with a new
pages
list that has the last item replaced. If the previousPage
and replacementPage
both have no key or the same key, then Flutter will treat them as the same page and will not animate. - Set
Navigator.transitionDelegate
to an object that extendsTransitionDelegate
. The delegate must check for a new record withRouteTransitionRecord.isWaitingForEnteringDecision
true and call itsmarkForAdd()
method. There is some useful code in https://github.com/flutter/flutter/issues/69315#issuecomment-833212172 .
Solution 9 - Navigation
Example with navigator 2.0 without animation
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
var userName = '';
var password = '';
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(context) {
return MaterialApp(
home: Navigator(
transitionDelegate: NoAnimationTransitionDelegate(),
pages: [
MaterialPage(child: HomePage()),
if (password.isEmpty) MaterialPage(child: PasswordPage()),
if (userName.isEmpty) MaterialPage(child: UserNamePage()),
],
onPopPage: (route, result) {
if (!route.didPop(result)) return false;
return true;
},
),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(context) {
return Scaffold(backgroundColor: Colors.blue);
}
}
class PasswordPage extends StatelessWidget {
@override
Widget build(context) {
return Scaffold(backgroundColor: Colors.amber);
}
}
class UserNamePage extends StatelessWidget {
@override
Widget build(context) {
return Scaffold(backgroundColor: Colors.green);
}
}
class NoAnimationTransitionDelegate extends TransitionDelegate<void> {
@override
Iterable<RouteTransitionRecord> resolve({
required List<RouteTransitionRecord> newPageRouteHistory,
required Map<RouteTransitionRecord?, RouteTransitionRecord> locationToExitingPageRoute,
required Map<RouteTransitionRecord?, List<RouteTransitionRecord>> pageRouteToPagelessRoutes,
}) {
final results = <RouteTransitionRecord>[];
for (final pageRoute in newPageRouteHistory) {
if (pageRoute.isWaitingForEnteringDecision) {
pageRoute.markForAdd();
}
results.add(pageRoute);
}
for (final exitingPageRoute in locationToExitingPageRoute.values) {
if (exitingPageRoute.isWaitingForExitingDecision) {
exitingPageRoute.markForRemove();
final pagelessRoutes = pageRouteToPagelessRoutes[exitingPageRoute];
if (pagelessRoutes != null) {
for (final pagelessRoute in pagelessRoutes) {
pagelessRoute.markForRemove();
}
}
}
results.add(exitingPageRoute);
}
return results;
}
}
Solution 10 - Navigation
This is without transitions. Only Fade in next page
class FadeInPageRoute<T> extends PageRoute<T> {
FadeInPageRoute({
RouteSettings? settings,
required this.builder,
}) : super(settings: settings);
final WidgetBuilder builder;
@override
Color get barrierColor => Colors.black;
@override
String get barrierLabel => '';
@override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return builder(context);
}
@override
bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {
return false;
}
@override
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return Opacity(
opacity: animation.value,
child: builder(context),
);
}
@override
bool get maintainState => true;
@override
Duration get transitionDuration => Duration(milliseconds: 700);
}