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

如何在Flutter GoRouter中添加动画,动画类能否独立存放调用

在Flutter GoRouter中添加页面切换动画及独立动画类实现

一、添加页面切换动画

GoRouter中自定义页面过渡需要用pageBuilder替代原代码中的builder,通过CustomTransitionPage配置过渡动画。以下是基于你提供的示例修改后的代码:

void main() => runApp(App());

class App extends StatelessWidget {
  App({Key? key}) : super(key: key);

  static const String title = 'GoRouter Example: Declarative Routes';

  @override
  Widget build(BuildContext context) => MaterialApp.router(
        routerConfig: _router,
        title: title,
      );

  final GoRouter _router = GoRouter(
    routes: <GoRoute>[
      GoRoute(
        path: '/',
        // 用pageBuilder替代builder,自定义过渡动画
        pageBuilder: (BuildContext context, GoRouterState state) => CustomTransitionPage(
          child: const Page1Screen(),
          transitionsBuilder: (context, animation, secondaryAnimation, child) {
            // 定义从右侧滑入的动画
            var begin = const Offset(1.0, 0.0);
            var end = Offset.zero;
            var curve = Curves.ease;
            var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
            return SlideTransition(
              position: animation.drive(tween),
              child: child,
            );
          },
        ),
        routes: <GoRoute>[
          GoRoute(
            path: 'page2',
            pageBuilder: (BuildContext context, GoRouterState state) => CustomTransitionPage(
              child: const Page2Screen(),
              transitionsBuilder: (context, animation, secondaryAnimation, child) {
                // 定义淡入动画
                return FadeTransition(
                  opacity: animation.drive(Tween(begin: 0.0, end: 1.0).chain(CurveTween(curve: Curves.easeInOut))),
                  child: child,
                );
              },
            ),
          ),
        ],
      ),
    ],
  );
}

二、将动画类存放在独立文件中

完全可以把动画逻辑封装到独立文件中,方便复用和管理。创建一个route_transitions.dart文件,把不同的动画封装成自定义CustomTransitionPage子类:

// route_transitions.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

// 右侧滑入动画页面
class SlideRightTransitionPage extends CustomTransitionPage {
  SlideRightTransitionPage({required Widget child})
      : super(
          child: child,
          transitionsBuilder: (context, animation, secondaryAnimation, child) {
            const begin = Offset(1.0, 0.0);
            const end = Offset.zero;
            const curve = Curves.ease;
            final tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
            return SlideTransition(
              position: animation.drive(tween),
              child: child,
            );
          },
        );
}

// 淡入淡出动画页面
class FadeTransitionPage extends CustomTransitionPage {
  FadeTransitionPage({required Widget child})
      : super(
          child: child,
          transitionsBuilder: (context, animation, secondaryAnimation, child) {
            return FadeTransition(
              opacity: animation.drive(Tween(begin: 0.0, end: 1.0).chain(CurveTween(curve: Curves.easeInOut))),
              child: child,
            );
          },
        );
}

// 缩放动画页面
class ScaleTransitionPage extends CustomTransitionPage {
  ScaleTransitionPage({required Widget child})
      : super(
          child: child,
          transitionsBuilder: (context, animation, secondaryAnimation, child) {
            return ScaleTransition(
              scale: animation.drive(Tween(begin: 0.8, end: 1.0).chain(CurveTween(curve: Curves.easeOut))),
              child: child,
            );
          },
        );
}

之后在主文件中导入该文件,直接在路由中使用这些动画类:

import 'route_transitions.dart';

// ...

final GoRouter _router = GoRouter(
  routes: <GoRoute>[
    GoRoute(
      path: '/',
      pageBuilder: (_, __) => SlideRightTransitionPage(child: const Page1Screen()),
      routes: <GoRoute>[
        GoRoute(
          path: 'page2',
          pageBuilder: (_, __) => FadeTransitionPage(child: const Page2Screen()),
        ),
        GoRoute(
          path: 'page3',
          pageBuilder: (_, __) => ScaleTransitionPage(child: const Page3Screen()),
        ),
      ],
    ),
  ],
);

额外说明

  • 你可以给动画类添加参数(比如动画时长、曲线),让动画配置更灵活
  • 如果需要全局默认过渡动画,可在GoRouter初始化时配置pageBuilder,个别路由再单独覆盖

内容的提问来源于stack exchange,提问作者George-Goldman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 17:35:34