Flutter 自定义路由与转场动画进阶指南

一、核心概念
  1. 路由本质
    Flutter 导航基于路由栈模型,每个页面对应一个 Route 对象,导航操作即路由栈的入栈/出栈操作
    $$ \text{路由栈} = [R_1, R_2, ..., R_n] \quad \text{其中} \quad R_i \in \text{Route} $$

  2. 动画原理
    转场动画通过 AnimationController 控制时间轴,结合 Tween 插值器实现属性过渡
    $$ \text{动画值} = Tween(begin, end).animate(CurvedAnimation(parent: controller, curve: curve)) $$

二、自定义路由实现
class CustomRoute<T> extends MaterialPageRoute<T> {
  CustomRoute({required WidgetBuilder builder, RouteSettings? settings})
      : super(builder: builder, settings: settings);

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation, Widget child) {
    // 此处返回自定义动画效果
    return ScaleTransition(
      scale: animation,
      child: FadeTransition(
        opacity: animation,
        child: child,
      ),
    );
  }
}

// 使用示例
Navigator.push(
  context,
  CustomRoute(builder: (context) => DetailPage()),
);

三、高级转场动画实现

1. 共享元素动画(Hero 增强)

// 起始页面
Hero(
  tag: 'image_$id',
  child: Image.network(imageUrl),
)

// 目标页面
Hero(
  tag: 'image_$id',
  flightShuttleBuilder: (flightContext, animation, flightDirection, 
      fromHeroContext, toHeroContext) {
    return ScaleTransition(
      scale: animation.drive(Tween(begin: 0.5, end: 1.0)),
      child: toHeroContext.widget,
    );
  },
  child: Image.network(imageUrl),
)

2. 物理引擎动画

@override
Widget buildTransitions(...) {
  return PhysicsCardDragTransition(
    animation: animation,
    secondaryAnimation: secondaryAnimation,
    child: child,
    spring: SpringDescription(
      mass: 0.5,
      stiffness: 100.0,
      damping: 10.0,
    ),
  );
}

3. 3D 旋转动画

@override
Widget buildTransitions(...) {
  return Rotation3DTransition(
    animation: animation,
    child: child,
    axis: Vector3(0.0, 1.0, 0.0), // Y轴旋转
    angle: π / 2, // 90度旋转
  );
}

四、性能优化技巧
  1. 动画复用
    使用 AnimationController 时遵循: $$ \text{创建开销} \gg \text{复用开销} $$

    final _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300)
    );
    

  2. 预加载策略
    复杂页面提前初始化:

    void initState() {
      Future.microtask(() => precacheImage(NetworkImage(url), context));
      super.initState();
    }
    

  3. 动画曲线选择
    根据场景选择最佳插值器:

    曲线类型 适用场景 数学表达式
    Curves.ease 通用过渡 $f(t)=t^2(3-2t)$
    Curves.elasticOut 弹跳效果 $f(t)=e^{-10t}\sin(10πt)$
五、跨平台适配方案
Widget buildTransitions(...) {
  if (Platform.isIOS) {
    return CupertinoPageTransition(...); 
  } else {
    return MaterialPageTransition(...);
  }
}

进阶提示

  • 使用 RouteObserver 监听路由生命周期
  • 通过 CustomClipper 实现自定义形状转场
  • 结合 ShaderMask 实现纹理动画

完整示例项目:[GitHub 仓库链接](实现包含20+种动画效果)

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐