Animation for named routes

2,601

Solution 1

I took chemamolins' advice and solved it in a similar way, but using maps.

I "extracted" the routes object and put it outside MaterialApp:

var routes = {
  '/': (context) => Login(),
  '/calendar': (context) => Calendar()
};

Then I used it inside onGenerateRoute:

Widget build(BuildContext context) {
  var routes = {
    '/': (context) => Login(),
    '/calendar': (context) => Calendar()
  };

  return MaterialApp(
    title: 'Demo',
    theme: myTheme,
    initialRoute: '/',
    onGenerateRoute: (settings) {
      return CupertinoPageRoute(builder: (context) => routes[settings.name](context));
    }
  );
}

Solution 2

You could leverage onGenerateRoute()

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  Route onGenerateRoute(RouteSettings settings) {
    Route page;
    switch (settings.name) {
      case "/":
        page = CupertinoPageRoute(builder: (context) => Login());
        break;
      case "/calendar":
        page = CupertinoPageRoute(builder: (context) => Calendar());
        break;
    }
    return page;
  }

  @override
  Widget build(BuildContext context) {
    return new WidgetsApp(
      onGenerateRoute: onGenerateRoute,
      initialRoute: "/",
    );
  }
}

Let's give a look to the Flutter code itself.

There is a framework provided onGenerateRoute() method called to generate the routes.

Look at the following snippet taken from the app.dart file in the framework.

  Route<dynamic> _onGenerateRoute(RouteSettings settings) {
    final String name = settings.name;
    WidgetBuilder builder;
    if (name == Navigator.defaultRouteName && widget.home != null) {
      builder = (BuildContext context) => widget.home;
    } else {
      builder = widget.routes[name];
    }
    if (builder != null) {
      return new MaterialPageRoute<dynamic>(
        builder: builder,
        settings: settings,
      );
    }
    if (widget.onGenerateRoute != null)
      return widget.onGenerateRoute(settings);
    return null;
  }

If the routes: provides a builder for a given name, it is used to generate the route using MaterialPageRoute by default. If it is not provided, it goes to generate it by using your onGenerateRoute() method.

Share:
2,601
BackSlash
Author by

BackSlash

I'm a programmer, I have no life.

Updated on December 07, 2022

Comments

  • BackSlash
    BackSlash over 1 year

    In Flutter we can customize the view-change animation by extending PageRoute (or by using a class which extends that).

    For instance, I'm changing the animation to "slide" in my MaterialApplication by using the CupertinoPageRoute that way:

    Navigator.of(context).pushReplacement(
      CupertinoPageRoute(builder: (context) => Calendar()),
    );
    

    Now I want to change that by using named views defined in the main.dart file:

    return MaterialApp(
      title: 'Demo',
      theme: myTheme, // => Theme.of(context).copyWith(...)
      initialRoute: '/',
      routes: {
        '/': (context) => Login(),
        '/calendar': (context) => Calendar(),
      }
    );
    

    This way I can just call

    Navigator.of(context).pushReplacementNamed('/calendar');
    

    Which is IMO clearer and view-agnostic.

    The issue with this approach is that I can't define a PageRoute, so I can't customize the view-change animation.

    Is there a way to do that?

  • BackSlash
    BackSlash over 5 years
    Isn't that a bit of a hack? I mean, what is the purpose of defining routes if I have to define them again in the onGenerateRoute method?
  • chemamolins
    chemamolins over 5 years
    I don't think it's a hack if you want to use named routes. In the routes: property you can't customize the route, you can just set the widget through the builder. By contrast, in onGenerateRoute() you can customize the Route. Let's say that routes: is the shortcut for onGenerateRoute: when you want to use default MaterialPageRoute.
  • chemamolins
    chemamolins over 5 years
    I have edited my answer to explain why this is not a hack if what the routes: property provides is not enough for you.
  • BackSlash
    BackSlash over 5 years
    Got it. I did it this way, but using a map rather than a switch-case. Thanks
  • BackSlash
    BackSlash over 5 years
    Any explainations for the downvote would be appreciated.
  • Paul
    Paul over 2 years
    Great, but how do you call a page with a specific animation? By calling this: Navigator.pushNamed(context, '/register'); I just get a slide left animation, but what if I want to change that to slide up/right/....?
  • BackSlash
    BackSlash over 2 years
    @Paul CupertinoPageRoute and MaterialPageRoute are built to behave the same as how native applications would, so there is no way to customize the animation direction. You can however build your own animation and make it exactly as needed.
  • Paul
    Paul over 2 years
    The problem is that I couldn't find an opportunity to do custom animations with named routes. Animation with your link: pageBuilder: (context, animation, secondaryAnimation) => const Page2() Is there a way to call the next page with the route-name?