BackSlash
BackSlash

Reputation: 22233

Animation for named routes

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?

Upvotes: 6

Views: 4183

Answers (2)

BackSlash
BackSlash

Reputation: 22233

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

Upvotes: 6

chemamolins
chemamolins

Reputation: 20548

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.

Upvotes: 2

Related Questions