How to remove default navigation route animation
Asked Answered
M

8

19

I am below code which given in flutter documentation for page routing

// Within the `FirstRoute` widget
onPressed: () {
  Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => SecondRoute()),
  );
}

But it provides some animation while pushing and popping route.

For Android, the entrance transition for the page slides the page upwards and fades it in. The exit transition is the same, but in reverse.

The transition is adaptive to the platform and on iOS, the page slides in from the right and exits in reverse. The page also shifts to the left in parallax when another page enters to cover it. (These directions are flipped in environments with a right-to-left reading direction.)

Is there any way to route to next page without any animation?

Edit: Please check the entire code:

class MyApp extends StatelessWidget {
  final routes = <String, WidgetBuilder>{
    SecondRoute.tag: (context) => SecondRoute(),
  };

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Routes",
      home: new FirstRoute(),
      routes: routes,
      onGenerateRoute: (routeSettings) {
        if (routeSettings.name == SecondRoute.tag)
          return PageRouteBuilder(pageBuilder: (_, a1, a2) => SecondRoute());

        return null;
      },
    );
  }
}

class FirstRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Route'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Open route'),
          onPressed: () {
            Navigator.of(context).pushNamed(SecondRoute.tag);

          },
        ),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  static String tag = 'second-route';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}
Minimalist answered 3/9, 2019 at 13:46 Comment(0)
T
30
  • For Navigator.push(...)

    Navigator.push(
      context,
      PageRouteBuilder(pageBuilder: (_, __, ___) => SecondRoute()),
    )
    
  • For Navigator.pushNamed(...)

    First, add this to your MaterialApp

    MaterialApp(
      onGenerateRoute: (settings) {
        if (settings.name == '/second') 
          return PageRouteBuilder(pageBuilder: (_, __, ___) => SecondRoute());
    
        return null;
      },
    )
    

    And now, you can use:

    Navigator.pushNamed(context, '/second');
    
Transit answered 3/9, 2019 at 14:43 Comment(8)
what is routeSettings here?Minimalist
routeSettings is the parameter which needs to be passed to onGenerateRoute, can you tell me if the solution worked?Transit
I checked it on Android, it's not working, it gives same animation for pushNamed.Minimalist
@CopsOnRoad: Please check my entire code. It will be helpful for you.Minimalist
Your code is fine, just remove routes: routes from it.Transit
it's working for me now, will accept your answer. but can elaborate why routes attribute not required and why it causing issue?Minimalist
@CopsOnRoad: Also what is the meaning of (_, a1, a2)? as in Rémi Rousselet answer, I see _, __, ___Minimalist
marvellous! For the pushNamed option: go sure to remove the /second from the routes table as onGenerateRoute seems to be a fallback when a route cannot be found in the routes tableWean
P
11

The animation is performed by MaterialPageRoute. If you don't want it, simple use something else:

Navigator.push(
  context,
  PageRouteBuilder(pageBuilder: (_, __, ___) => MyRoute()),
)
Piapiacenza answered 3/9, 2019 at 13:50 Comment(5)
also, I figured out Navigator.of(context).pushNamed(SecondRoute.tag); also does the same animation, how we can avoid there?Minimalist
@jitsm555 That's also done with MaterialPageRoute internally.Transit
@CopsOnRoad: How we can remove the animation from there?Minimalist
@jitsm555 You can do that in MaterialApp onGenerateRoute.Transit
@jitsm555 Check out my answer.Transit
F
3

As Flutter is now migrating to Navigator 2.0 for increased support, I would recommend checking out their migration guide on adding a TransitionDelegate to the Navigator. Add an instance of this class to your navigator to achieve the intended result:

import 'package:flutter/widgets.dart';

class NoAnimationTransitionDelegate extends TransitionDelegate<void> {
  @override
  Iterable<RouteTransitionRecord> resolve({
    List<RouteTransitionRecord> newPageRouteHistory,
    Map<RouteTransitionRecord, RouteTransitionRecord> locationToExitingPageRoute,
    Map<RouteTransitionRecord, List<RouteTransitionRecord>> pageRouteToPagelessRoutes,
  }) {
    final List<RouteTransitionRecord> results = <RouteTransitionRecord>[];

    for (final RouteTransitionRecord pageRoute in newPageRouteHistory) {
      // Renames isEntering to isWaitingForEnteringDecision.
      if (pageRoute.isWaitingForEnteringDecision) {
        pageRoute.markForAdd();
      }
      results.add(pageRoute);

    }
    for (final RouteTransitionRecord exitingPageRoute in locationToExitingPageRoute.values) {
      // Checks the isWaitingForExitingDecision before calling the markFor methods.
      if (exitingPageRoute.isWaitingForExitingDecision) {
        exitingPageRoute.markForRemove();
        final List<RouteTransitionRecord> pagelessRoutes = pageRouteToPagelessRoutes[exitingPageRoute];
        if (pagelessRoutes != null) {
          for (final RouteTransitionRecord pagelessRoute in pagelessRoutes) {
            pagelessRoute.markForRemove();
          }
        }
      }
      results.add(exitingPageRoute);

    }
    return results;
   }
 }
Femme answered 2/2, 2021 at 18:15 Comment(0)
T
2

Replace your MyApp with this.

class MyApp extends StatelessWidget {
  final routes = <String, WidgetBuilder>{SecondRoute.tag: (context) => SecondRoute()};

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Routes",
      home: new FirstRoute(),
      onGenerateRoute: (routeSettings) {
        if (routeSettings.name == SecondRoute.tag)
          return PageRouteBuilder(
            pageBuilder: (_, a1, a2) => FadeTransition(opacity: a1 ,child: SecondRoute()),
            transitionDuration: Duration(seconds: 5),
          );

        return null;
      },
    );
  }
}
Transit answered 3/9, 2019 at 15:17 Comment(0)
C
1

If you are using routs, here is the full code to get the permanent solution

      void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await ScreenUtil.ensureScreenSize();
      await ServiceLocator.setUpServiceLocator();
      initializeLoggerServer();
      serviceLocator.get<Log>().shout('App Initialized Successfully');
      runApp(AgrotopiaApp());
    }
    
    void initializeLoggerServer() {
      Logger.root.level = Level.ALL; // defaults to Level.INFO
      Logger.root.onRecord.listen((record) {
        debugPrint('${record.level.name}: ${record.time}: ${record.message}');
      });
    }
      //create this class to make no animation 
    class NoAnimationPageRoute<T> extends MaterialPageRoute<T> {
      NoAnimationPageRoute({required WidgetBuilder builder, required RouteSettings settings})
          : super(builder: builder, settings: settings);
    
      @override
      Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
        return FadeTransition(opacity: AlwaysStoppedAnimation(1.0), child: child);
      }
    }
    
   
    class FadePageRoute<T> extends MaterialPageRoute<T> {
      FadePageRoute({required WidgetBuilder builder, required RouteSettings settings})
          : super(builder: builder, settings: settings);
    
      @override
      Widget buildTransitions(BuildContext context, Animation<double> animation,
          Animation<double> secondaryAnimation, Widget child) {
        return FadeTransition(opacity: animation, child: child);
      }
    }
    
    
    class AgrotopiaApp extends StatelessWidget {
      AgrotopiaApp({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return ScreenUtilInit(
            designSize: context.resources.variables.screenDesignSize,
            splitScreenMode: false,
            minTextAdapt: true,
            useInheritedMediaQuery: false,
            builder: (BuildContext context, Widget? child) {
              return MultiProvider(
                providers: [
                  ChangeNotifierProvider(
                      create: (_) => LoaderModelView(), lazy: true),
                  ChangeNotifierProvider(
                      create: (_) => GlobalAppProvider(), lazy: true),
                  ChangeNotifierProvider(
                      create: (_) => OnBoardingViewModel(), lazy: true),
                  ChangeNotifierProvider(
                      create: (_) => BottomNavViewModel(), lazy: true),
                  ChangeNotifierProvider(
                      create: (_) => PlaceOrderViewModel(), lazy: true),
                  ChangeNotifierProvider(
                      create: (_) => PaymentViewModel(), lazy: true),
                ],
                child: MaterialApp(
                    navigatorKey: GlobalKey<NavigatorState>(),
                    title: context.resources.variables.appName,
                    debugShowCheckedModeBanner: false,
                    theme: context.resources.styles.appTheme(),
                    home: const SplashScreen(),
                    // home: CollectUserData(),
                    // home: const UserOnBoardingPage(),
                    initialRoute: '/',
                     onGenerateRoute: (RouteSettings settings) {
                      
            switch (settings.name) {
              
              case '/home':
                return NoAnimationPageRoute(builder: (_) => HomePage(), settings: settings);
              case '/app':
                return NoAnimationPageRoute(builder: (_) => AgrotopiaApp(), settings: settings);
              case '/settingpage':
                return NoAnimationPageRoute(builder: (_) => SettingPage(), settings: settings);
              case '/placeordermenu':
                return NoAnimationPageRoute(builder: (_) => PlaceOrderMenu(), settings: settings);
              case '/placeorderpage':
                return NoAnimationPageRoute(builder: (_) => PlaceOrderPage(), settings: settings);
              case '/paymentinformationpage':
                return NoAnimationPageRoute(builder: (_) => PaymentInformationPage(), settings: settings);
              case '/orderstatuspage':
                return NoAnimationPageRoute(builder: (_) => OrderStatusPage(), settings: settings);
              case '/orderdetailspage':
                return NoAnimationPageRoute(builder: (_) => OrderDetailsPage(), settings: settings);
              case '/confirmation':
                return NoAnimationPageRoute(builder: (_) => Confirmation(), settings: settings);
              // case '/orderdetailspage':
              //   return NoAnimationPageRoute(builder: (_) => OrderDetailsPage(), settings: settings);
              default:
                return MaterialPageRoute(builder: (_) => Scaffold());
            }
          },
                    
            
                    ),
              );
            });
      }
    }

now do navigate to another page

  Navigator.pushNamed(context,'/orderstatuspage');
Cygnus answered 27/2, 2023 at 9:49 Comment(0)
T
1

Remove it at Material Configuration level:

First, create a custom Page Transition (with no transition at all)

class _NoTransitionsBuilder extends PageTransitionsBuilder {
  const _NoTransitionsBuilder();

  @override
  Widget buildTransitions<T>(
    PageRoute<T>? route,
    BuildContext? context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
    Widget? child,
  ) {
    return child!;
  }
}

Then create a PageTransitionsTheme:

PageTransitionsTheme _removeTransitions() {
  return PageTransitionsTheme(
    builders: {
      for (final platform in TargetPlatform.values)
        platform: const _NoTransitionsBuilder(),
    },
  );
}

Finally, add the new Transitions Theme on your MaterialApp constructor

@override
Widget build(BuildContext context) {
  return MaterialApp(
    // ...
    theme: ThemeData(
      pageTransitionsTheme: _removeTransitions(),
    ),
  );
}
Tumbledown answered 24/8, 2023 at 11:51 Comment(0)
E
1

@Yasser Nascimento's answer is good except it naively disables animations for all platforms, which is likely undesirable.

To disable animations for specific platforms, define a NoTransitionsBuilder class like:

class NoTransitionsBuilder extends PageTransitionsBuilder {
  const NoTransitionsBuilder();

  @override
  Widget buildTransitions<T>(
    PageRoute<T>? route,
    BuildContext? context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
    Widget? child,
  ) {
    return child!;
  }
}

And then in ThemeData configure the pageTransitionsTheme:

pageTransitionsTheme: const PageTransitionsTheme(
  builders: <TargetPlatform, PageTransitionsBuilder>{
    TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
      TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
      TargetPlatform.linux: NoTransitionsBuilder(),
      TargetPlatform.macOS: NoTransitionsBuilder(),
      TargetPlatform.windows: NoTransitionsBuilder(),
  },
),

Notes

See issue #99052 for:

  • original post of this workaround from tmpfs
  • my comment highlighting that a finer-grained solution for configuring animations for web (at least) is necessary
Exile answered 17/9, 2023 at 23:35 Comment(0)
M
0

aidan marshal's solution is simple and works fine but there some adjustments in his code

 import 'package:flutter/widgets.dart';

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 List<RouteTransitionRecord> results = <RouteTransitionRecord>[];

     for (final RouteTransitionRecord pageRoute in newPageRouteHistory) {
      // Renames isEntering to isWaitingForEnteringDecision.
      if (pageRoute.isWaitingForEnteringDecision) {
        pageRoute.markForAdd();
      }
      results.add(pageRoute);

    }
    for (final RouteTransitionRecord exitingPageRoute in locationToExitingPageRoute.values) {
      // Checks the isWaitingForExitingDecision before calling the markFor methods.
      if (exitingPageRoute.isWaitingForExitingDecision) {
        exitingPageRoute.markForRemove();
        final List<RouteTransitionRecord>? pagelessRoutes = pageRouteToPagelessRoutes[exitingPageRoute];
        if (pagelessRoutes != null) {
          for (final RouteTransitionRecord pagelessRoute in pagelessRoutes) {
            pagelessRoute.markForRemove();
          }
        }
      }
      results.add(exitingPageRoute);

    }
    return results;
   }
  }
 }
Misogamy answered 19/4, 2022 at 22:33 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.