正如 go_router 的文档所描述的,很容易设置 pageBuilder
-单个页面的转换。 但是,我想为所有页面设置默认的 PageTransition。 如何在 Flutter 中使用 go_router 设置默认页面转换?
单页:
// this is the proposed method to do it for single pages
// how can i apply it to all pages without writing the same code?
GoRoute(
path: '/login',
builder: (context, state) => const LoginScreen(),
pageBuilder: (context, state) => CustomTransitionPage<void>(
key: state.pageKey,
child: const LoginScreen(),
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
FadeTransition(opacity: animation, child: child),
),
),
致以诚挚的问候
go_router
包目前不支持此功能,但为了减少代码重复,您可以创建一个辅助函数来为您的路线应用自定义转换,例如:
CustomTransitionPage buildPageWithDefaultTransition<T>({
required BuildContext context,
required GoRouterState state,
required Widget child,
}) {
return CustomTransitionPage<T>(
key: state.pageKey,
child: child,
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
FadeTransition(opacity: animation, child: child),
);
}
<...>
GoRoute(
path: '/login',
builder: (context, state) => const LoginScreen(),
pageBuilder: (context, state) => buildPageWithDefaultTransition<void>(
context: context,
state: state,
child: LoginScreen(),
),
),
CustomTransitionPage
。
class WebPage extends CustomTransitionPage {
WebPage({
LocalKey key,
... // other properties taken from `MaterialPage`
required Widget child
}) : super(
key: key,
transitionBuilder: (...) {
return FadeTransition(...);
}
child: child, // Here you may also wrap this child with some common designed widget
);
}
然后
GoRoute(
path: '/login',
pageBuilder: (context, state) => WebPage(
key: state.pageKey,
child: const LoginScreen(),
),
),
CustomTransitionPage buildPageWithDefaultTransition<T>({
required BuildContext context,
required GoRouterState state,
required Widget child,
}) {
return CustomTransitionPage<T>(
key: state.pageKey,
child: child,
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
FadeTransition(opacity: animation, child: child),
);
}
Page<dynamic> Function(BuildContext, GoRouterState) defaultPageBuilder<T>(
Widget child) =>
(BuildContext context, GoRouterState state) {
return buildPageWithDefaultTransition<T>(
context: context,
state: state,
child: child,
);
};
路由器看起来像:
final _router = GoRouter(
routes: [
GoRoute(
path: '/a',
builder: (context, state) => const PageA(),
pageBuilder: defaultPageBuilder(const PageA()),
),
GoRoute(
path: '/b',
builder: (context, state) => const PageB(),
pageBuilder: defaultPageBuilder(const PageB()),
),
],
);
scale
、
rotation
和
size
。
Rotation
按照我的口味转了太多次,
size
看起来几乎没有过渡效果,但是
scale
还不错。
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class RouterTransitionFactory {
static CustomTransitionPage getTransitionPage(
{required BuildContext context,
required GoRouterState state,
required Widget child,
required String type}) {
return CustomTransitionPage(
key: state.pageKey,
child: child,
transitionsBuilder: (context, animation, secondaryAnimation, child) {
switch (type) {
case 'fade':
return FadeTransition(opacity: animation, child: child);
case 'rotation':
return RotationTransition(turns: animation, child: child);
case 'size':
return SizeTransition(sizeFactor: animation, child: child);
case 'scale':
return ScaleTransition(scale: animation, child: child);
default:
return FadeTransition(opacity: animation, child: child);
}
});
}
}
应该这样称呼:
GoRoute(
path: '/settings',
builder: (context, state) => const Settings(), //StatelessWidget
pageBuilder: (context, state) => RouterTransitionFactory.getTransitionPage(
context: context,
state: state,
child: const Settings(),
type: 'scale', // fade|rotation|scale|size
),
),
GoRoute defaultTransitionGoRoute({
required String path,
required Widget Function(BuildContext, GoRouterState) pageBuilder,
}) {
return GoRoute(
path: path,
pageBuilder: (context, state) => CustomTransitionPage<void>(
key: state.pageKey,
transitionDuration: const Duration(milliseconds: 300),
child: pageBuilder(context, state),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: CurveTween(curve: Curves.easeIn).animate(animation),
child: child,
);
},
),
);
}
然后使用like
GoRoute(
path: ScreenPaths.favorites,
builder: (context, state) => FavorateScreen(),
),
defaultTransitionGoRoute(
path: ScreenPaths.viewEmail,
pageBuilder: (context, state) {
final extra = state.extra;
return ViewEmailScreen(
email: extra as HiveEmail,
);
},
),