颤动:动画过渡到命名路线

时间:2019-06-27 13:47:00

标签: flutter flutter-animation

当我使用Navigator.pushNamed(context, "/someRoute");时,会有一个最小的动画,它会从屏幕底部沿新路线滑动(在Android上,在iOS上可能看起来有所不同)。

如何在此过渡中添加自定义动画?

我发现this article,其中有一些非常整洁的示例代码,用于未命名路由。它们实现了自己的类,该类继承自PageRouteBuilder,可以像这样使用:Navigator.push(context, SlideRightRoute(page: Screen2()))。但是PageRouteBuilder不是小部件,不能在MaterialApp中注册为路由。因此,我看不到如何将其应用于命名路由。

3 个答案:

答案 0 :(得分:1)

无需 onGenerateRoute 即可使用动画路线!

如果您使用 MaterialApproutes 映射来定义命名路由,以下是定义命名路由(其名称不会是 null)的方法。

只需通过扩展 PageRouteBuilder 来创建您的路线:

import 'package:flutter/material.dart';

class FadeInRoute extends PageRouteBuilder {
  final Widget page;

  FadeInRoute({this.page, String routeName})
      : super(
          settings: RouteSettings(name: routeName),            // set name here
          pageBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
          ) =>
              page,
          transitionsBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
            Widget child,
          ) =>
              FadeTransition(
            opacity: animation,
            child: child,
          ),
          transitionDuration: Duration(milliseconds: 500),
        );
}

然后在导航时,只需执行以下操作:

Navigator.push( // or pushReplacement, if you need that
  context,
  FadeInRoute(
    routeName: RouteNames.home,
    page: MyHomeScreen(),
  ),
);

答案 1 :(得分:1)

我找到了一个简单的解决方案(灵感来自 this code

首先需要为 MaterialApp 设置一个静态的 GlobalKey 并导出

static GlobalKey mtAppKey = GlobalKey();

Widget build(BuildContext context) {
  return MaterialApp(
    key: MyApp.mtAppKey,
    ...

另外,你需要一个自定义的 PageRouteBuilder 来处理它

Null-safety 禁用

class CustomNamedPageTransition extends PageRouteBuilder {
  CustomNamedPageTransition(
    GlobalKey materialAppKey,
    String routeName, {
    Object arguments,
  }) : super(
          settings: RouteSettings(
            arguments: arguments,
            name: routeName,
          ),
          pageBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
          ) {
            assert(materialAppKey.currentWidget != null);
            assert(materialAppKey.currentWidget is MaterialApp);
            var mtapp = materialAppKey.currentWidget as MaterialApp;
            var routes = mtapp.routes;
            assert(routes.containsKey(routeName));
            return routes[routeName](context);
          },
          transitionsBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
            Widget child,
          ) =>
              FadeTransition(
            opacity: animation,
            child: child,
          ),
          transitionDuration: Duration(seconds: 1),
        );
}

启用空安全

class CustomNamedPageTransition extends PageRouteBuilder {
  CustomNamedPageTransition(
    GlobalKey materialAppKey,
    String routeName, {
    Object? arguments,
  }) : super(
          settings: RouteSettings(
            arguments: arguments,
            name: routeName,
          ),
          pageBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
          ) {
            assert(materialAppKey.currentWidget != null);
            assert(materialAppKey.currentWidget is MaterialApp);
            var mtapp = materialAppKey.currentWidget as MaterialApp;
            var routes = mtapp.routes;
            assert(routes!.containsKey(routeName));
            return routes![routeName]!(context);
          },
          transitionsBuilder: (
            BuildContext context,
            Animation<double> animation,
            Animation<double> secondaryAnimation,
            Widget child,
          ) =>
              FadeTransition(
            opacity: animation,
            child: child,
          ),
          transitionDuration: Duration(seconds: 1),
        );
}

然后,您可以使用

打开您的命名路线
Navigator.push(
  context,
  CustomNamedPageTransition(
    MyApp.mtAppKey,
    MyRoute.routeName,
  ),
);

Navigator.pushReplacement(
  context,
  CustomNamedPageTransition(
    MyApp.mtAppKey,
    MyRoute.routeName,
  ),
);

答案 2 :(得分:0)

您需要在onGenerateRoute小部件中使用MaterialApp

onGenerateRoute: (settings) {
  if (settings.name == "/someRoute") {
    return PageRouteBuilder(
      pageBuilder: (context, anim1, anim2) => SomePage(),
      transitionsBuilder: (context, anim1, anim2, child) {
        return FadeTransition(opacity: anim1, child: child);
      },
    );
  }
  // unknown route
  return MaterialPageRoute(builder: (context) => UnknownPage());
},