79

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(),
      },
    );
  }
}
Mauricio De armas
  • 2,079
  • 3
  • 11
  • 15

10 Answers10

123

You can use PageRouteBuilder.

Navigator.pushReplacement(
    context, 
    PageRouteBuilder(
        pageBuilder: (context, animation1, animation2) => Page1(),
        transitionDuration: Duration.zero,
        reverseTransitionDuration: Duration.zero,
    ),
);
Edwin Liu
  • 7,413
  • 3
  • 28
  • 27
36

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;
  }
}
lsaudon
  • 1,263
  • 11
  • 24
  • 1
    Any way to determine whether the animation is for opening or closing? I'd like to keep the animation for closing. – Janneman Nov 26 '19 at 16:40
  • @Janneman I don't know, but you can try to keep animation or secondaryAnimation. https://github.com/flutter/flutter/blob/b31ca1aaca0b9ef70ec478a74b3b690e4d632616/packages/flutter/lib/src/material/page.dart line 105 – lsaudon Nov 27 '19 at 08:16
  • Amazing stuff!! – James 666 May 17 '21 at 16:28
  • 1
    why not just https://stackoverflow.com/a/57774013/5060513? can you explain the plus and drawbacks? – Taufik Nur Rahmanda Oct 08 '21 at 12:55
21

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),
  ),
);
Philippe Fanaro
  • 6,148
  • 6
  • 38
  • 76
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
  • that is correct with duration to zero seconds method we get delay on closing route. and that is very annoying look like a lug. – Fuad All May 25 '20 at 22:59
  • 6
    And there's `reverseTransitionDuration`, which you can set to `0` also. – Tayan Sep 04 '21 at 09:57
21

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();
    },
  ),
);
Philippe Fanaro
  • 6,148
  • 6
  • 38
  • 76
Pavel Shastov
  • 2,657
  • 1
  • 18
  • 26
9

EDIT: This simple solution longer works. See https://github.com/flutter/flutter/issues/51649 .

Good luck using the Navigator 2.0 API.


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(),
                    ],
                  ),
                ),
              ),
            ),
      },
    ),
  );
}

screen recording

M. Leonhard
  • 1,332
  • 1
  • 18
  • 20
6

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.

Iván Yoed
  • 3,878
  • 31
  • 44
5

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;
 }
}
Jidong Chen
  • 450
  • 6
  • 9
1

With Navigator 2.0, there are two ways:

  1. 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.
  2. Set Navigator.transitionDelegate to an object that extends TransitionDelegate. The delegate must check for a new record with RouteTransitionRecord.isWaitingForEnteringDecision true and call its markForAdd() method. There is some useful code in https://github.com/flutter/flutter/issues/69315#issuecomment-833212172 .
M. Leonhard
  • 1,332
  • 1
  • 18
  • 20
1

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;
  }
}
Yauheni Prakapenka
  • 1,056
  • 11
  • 10
0

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);
}

Peter
  • 33
  • 7