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

flutter: animate transition to named route

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

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

我发现 this article,它有一些非常简洁的 未命名 路由示例代码。他们实现了自己的 class,它继承自 PageRouteBuilder,可以像这样使用:Navigator.push(context, SlideRightRoute(page: Screen2()))。但是 PageRouteBuilder 不是 Widget,不能在 MaterialApp 中注册为路由。所以我不知道如何将其应用于命名路由。

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

onGenerateRoute: (settings) {
  if (settings.name == "/someRoute") {
    return PageRouteBuilder(
      settings: settings, // Pass this to make popUntil(), pushNamedAndRemoveUntil(), works
      pageBuilder: (_, __, ___) => SomePage(),
      transitionsBuilder: (_, a, __, c) => FadeTransition(opacity: a, child: c)
    );
  }
  // Unknown route
  return MaterialPageRoute(builder: (_) => UnknownPage());
},

没有 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(),
  ),
);

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

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

static GlobalKey mtAppKey = GlobalKey();

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

此外,您需要自定义 PageRouteBuilder 来处理它

空安全已禁用

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