如何通过多个Tween为同一属性分阶段提供动画值?
解决Flutter同一属性多段Tween动画覆盖问题
方案一:使用TweenSequence(官方推荐)
TweenSequence专门用于组合多段连续动画,支持为每个片段设置时间权重,完美匹配你的分段动画需求。修改后的代码如下:
class TextAnimation extends StatelessWidget { const TextAnimation({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final Animation<double> yOffset = TweenSequence<double>( [ TweenSequenceItem( tween: Tween<double>(begin: 0.0, end: 180.0) .chain(CurveTween(curve: Curves.easeIn)), weight: 0.5, // 对应总动画时长的50% ), TweenSequenceItem( tween: Tween<double>(begin: 180.0, end: -100.0) .chain(CurveTween(curve: Curves.easeOut)), weight: 0.5, // 对应总动画时长的50% ), ], ).animate(animationController); return AnimatedBuilder( animation: animationController, builder: (context, child) { return Transform.translate( offset: Offset(0, yOffset.value), child: const Text("Hello"), ); }, ); } }
注意:第二段Tween的begin需与第一段的end保持一致,保证动画衔接流畅;weight比例对应你原本的Interval区间,比如0.5对应0.0-0.5的时间范围。
方案二:手动根据动画控制器值计算
若不想依赖Tween,可直接读取animationController.value(范围0.0-1.0),判断当前时间区间后手动计算属性值,灵活性更高:
class TextAnimation extends StatelessWidget { const TextAnimation({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return AnimatedBuilder( animation: animationController, builder: (context, child) { double y; final progress = animationController.value; if (progress <= 0.5) { // 0.0-0.5阶段:从0到180,应用easeIn曲线 final segmentProgress = Curves.easeIn.transform(progress * 2); y = 0.0 + (180.0 - 0.0) * segmentProgress; } else { // 0.5-1.0阶段:从180到-100,应用easeOut曲线 final segmentProgress = Curves.easeOut.transform((progress - 0.5) * 2); y = 180.0 + (-100.0 - 180.0) * segmentProgress; } return Transform.translate( offset: Offset(0, y), child: const Text("Hello"), ); }, ); } }
方案三:保留多个Animation变量,按需取值
不覆盖原有Animation对象,定义两个独立变量,在builder中根据控制器当前值判断使用哪段动画的结果:
class TextAnimation extends StatelessWidget { const TextAnimation({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final Animation<double> yOffset1 = Tween<double>( begin: 0.0, end: 180.0, ).animate( CurvedAnimation( parent: animationController, curve: const Interval(0.0, 0.5, curve: Curves.easeIn), ), ); final Animation<double> yOffset2 = Tween<double>( begin: 180.0, end: -100.0, ).animate( CurvedAnimation( parent: animationController, curve: const Interval(0.5, 1.0, curve: Curves.easeOut), ), ); return AnimatedBuilder( animation: animationController, builder: (context, child) { final y = animationController.value <= 0.5 ? yOffset1.value : yOffset2.value; return Transform.translate( offset: Offset(0, y), child: const Text("Hello"), ); }, ); } }
内容的提问来源于stack exchange,提问作者Nullable
相关产品推荐
相关产品推荐

