You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中两个GoRoute使用pageBuilder时过渡动画失效问题

问题解答

1. 实现A与B双向淡入淡出过渡的方案

你需要在CustomTransitionPage的transitionsBuilder中同时处理新页面的进入动画和旧页面的退出动画,通过Stack将两个页面的动画逻辑结合,确保双向切换都能呈现淡入淡出效果。修改后的路由配置如下:

final routes = GoRouter(routes: <RouteBase>[
  GoRoute(
    path: "/A",
    pageBuilder: (context, state) => CustomTransitionPage(
      child: const ViewA(),
      transitionDuration: const Duration(seconds: 2),
      transitionsBuilder: (context, animation, secondaryAnimation, child) => Stack(
        children: [
          // 旧页面退出动画:反向利用secondaryAnimation实现淡出
          if (secondaryAnimation.status != AnimationStatus.dismissed)
            FadeTransition(
              opacity: CurveTween(curve: Curves.easeInOutCirc)
                  .animate(ReverseAnimation(secondaryAnimation)),
              child: context.findAncestorWidgetOfExactType<CustomTransitionPage>()?.child,
            ),
          // 新页面进入动画:用animation控制淡入
          FadeTransition(
            opacity: CurveTween(curve: Curves.easeInOutCirc).animate(animation),
            child: child,
          ),
        ],
      ),
    ),
  ),
  GoRoute(
    path: "/B",
    pageBuilder: (context, state) => CustomTransitionPage(
      child: const ViewB(),
      transitionDuration: const Duration(seconds: 2),
      transitionsBuilder: (context, animation, secondaryAnimation, child) => Stack(
        children: [
          if (secondaryAnimation.status != AnimationStatus.dismissed)
            FadeTransition(
              opacity: CurveTween(curve: Curves.easeInOutCirc)
                  .animate(ReverseAnimation(secondaryAnimation)),
              child: context.findAncestorWidgetOfExactType<CustomTransitionPage>()?.child,
            ),
          FadeTransition(
            opacity: CurveTween(curve: Curves.easeInOutCirc).animate(animation),
            child: child,
          ),
        ],
      ),
    ),
  ),
]);

如果想简化代码,可以把过渡逻辑抽成复用函数:

Widget _fadeTransitionBuilder(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
  return Stack(
    children: [
      if (secondaryAnimation.status != AnimationStatus.dismissed)
        FadeTransition(
          opacity: CurveTween(curve: Curves.easeInOutCirc)
              .animate(ReverseAnimation(secondaryAnimation)),
          child: context.findAncestorWidgetOfExactType<CustomTransitionPage>()?.child,
        ),
      FadeTransition(
        opacity: CurveTween(curve: Curves.easeInOutCirc).animate(animation),
        child: child,
      ),
    ],
  );
}

之后在两个路由的transitionsBuilder中直接调用该函数即可。

2. 双路由配置过渡动画后失效的原因

当两个路由都使用CustomTransitionPage时,context.go属于替换路由栈的操作,GoRouter会同时触发旧页面的退出动画和新页面的进入动画。但你最初的代码只处理了新页面的进入(仅用animation控制透明度),完全没有利用secondaryAnimation处理旧页面的退出逻辑。

这种情况下,新旧页面的动画叠加后,视觉上呈现为直接切换,看不到任何过渡效果。而当其中一个路由用builder(默认MaterialPage)时,GoRouter会用默认过渡逻辑配合自定义页面的动画,所以能看到单向的淡入效果。

内容的提问来源于stack exchange,提问作者Felix ZY

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 06:25:17