当我使用Navigator.pushNamed(context, "/someRoute");
时,会有一个最小的动画,它会从屏幕底部沿新路线滑动(在Android上,在iOS上可能看起来有所不同)。
如何在此过渡中添加自定义动画?
我发现this article,其中有一些非常整洁的示例代码,用于未命名路由。它们实现了自己的类,该类继承自PageRouteBuilder
,可以像这样使用:Navigator.push(context, SlideRightRoute(page: Screen2()))
。但是PageRouteBuilder
不是小部件,不能在MaterialApp
中注册为路由。因此,我看不到如何将其应用于命名路由。
答案 0 :(得分:1)
无需 onGenerateRoute
即可使用动画路线!
如果您使用 MaterialApp
的 routes
映射来定义命名路由,以下是定义命名路由(其名称不会是 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());
},