在 Flutter 中设置 go_router 的默认转换

Mar*_*sky 16 navigation animation transition flutter gorouter

正如go_router 的文档所描述的,为单个页面设置pageBuilder-Transitions 很容易。但是,我想为所有页面设置默认的 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),
      ),
    ),
Run Code Online (Sandbox Code Playgroud)

此致

mko*_*lys 33

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',
  pageBuilder: (context, state) => buildPageWithDefaultTransition<void>(
    context: context, 
    state: state, 
    child: LoginScreen(),
  ),
),
Run Code Online (Sandbox Code Playgroud)

  • 有用。已投赞成票。我想知道“transitionBuilder”、“animation”和“ secondaryAnimation”对象的调用来自哪里? (2认同)

Bam*_*oUA 7

更正确的方法是继承自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
       );
}
Run Code Online (Sandbox Code Playgroud)

然后

GoRoute(
  path: '/login',
  pageBuilder: (context, state) => WebPage(
    key: state.pageKey,
    child: const LoginScreen(),
  ),
),
Run Code Online (Sandbox Code Playgroud)


nhC*_*der 7

为什么不这样使用它比接受的答案更容易

GoRoute TransitionGoRoute({
  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,
        );
      },
    ),
  );
}
Run Code Online (Sandbox Code Playgroud)

然后使用像

    TransitionGoRoute(
      path: ScreenPaths.viewEmail,
      pageBuilder: (context, state) {
        final extra = state.extra;
        return ViewEmailScreen(
          email: extra as HiveEmail,
        );
      },
    ),
Run Code Online (Sandbox Code Playgroud)


小智 5

扩展@mkobuolys答案,可以通过返回创建页面构建器的函数进一步减少样板,即:

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,
      );
    };
Run Code Online (Sandbox Code Playgroud)

路由器看起来像:

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()),
    ),
  ],
);
Run Code Online (Sandbox Code Playgroud)