如何链式调用SlideTransition实现多阶段滑动动画?
实现多阶段动画方案
你可以通过监听动画状态结合Future.delayed,或者使用TweenSequence组合动画段,来完成这三个阶段的动画逻辑。以下是两种可行方案:
方案一:使用TweenSequence组合完整动画序列
这种方式将所有动画阶段整合到一个控制器中,逻辑更简洁,适合固定时长的场景:
class YourWidget extends StatefulWidget { final Duration duration; const YourWidget({super.key, required this.duration}); @override State<YourWidget> createState() => _YourWidgetState(); } class _YourWidgetState extends State<YourWidget> with SingleTickerProviderStateMixin { late AnimationController animationController; late Animation<Offset> slideAnimation; late Animation<double> opacityAnimation; @override void initState() { super.initState(); // 总时长 = 第一段移动时长 + 等待时长 + 第二段移动消失时长 final totalDuration = widget.duration + const Duration(seconds: 2) + const Duration(seconds: 1); animationController = AnimationController(duration: totalDuration, vsync: this); // 位移动画序列:位置1→位置2 → 保持位置2 → 位置2→位置3 slideAnimation = TweenSequence([ TweenSequenceItem( tween: Tween<Offset>(begin: const Offset(1.0, 0), end: const Offset(0.0, 0)), weight: widget.duration.inMilliseconds.toDouble(), ), TweenSequenceItem( tween: ConstantTween<Offset>(const Offset(0.0, 0)), weight: 2000.0, ), TweenSequenceItem( tween: Tween<Offset>(begin: const Offset(0.0, 0), end: const Offset(-1.0, 0)), weight: 1000.0, ), ]).animate(animationController); // 透明度动画:前两段保持不透明,最后一段渐变消失 opacityAnimation = TweenSequence([ TweenSequenceItem( tween: ConstantTween<double>(1.0), weight: widget.duration.inMilliseconds.toDouble() + 2000.0, ), TweenSequenceItem( tween: Tween<double>(begin: 1.0, end: 0.0), weight: 1000.0, ), ]).animate(animationController); } @override Widget build(BuildContext context) { return GestureDetector( onTap: () { // 点击播放按钮启动动画,from:0支持重复触发 animationController.forward(from: 0); }, child: FadeTransition( opacity: opacityAnimation, child: SlideTransition( position: slideAnimation, child: getBarrageWidget(), ), ), ); } @override void dispose() { animationController.dispose(); super.dispose(); } Widget getBarrageWidget() { // 自定义组件示例,可替换为你的实际组件 return Container( width: 100, height: 50, color: Colors.blue, child: const Center(child: Text("弹幕")), ); } }
方案二:分阶段监听动画状态执行
这种方式更灵活,适合需要动态调整等待时长或动画参数的场景:
class YourWidget extends StatefulWidget { final Duration duration; const YourWidget({super.key, required this.duration}); @override State<YourWidget> createState() => _YourWidgetState(); } class _YourWidgetState extends State<YourWidget> with SingleTickerProviderStateMixin { late AnimationController animationController; late Animation<Offset> slideAnimation; late Animation<double> opacityAnimation; @override void initState() { super.initState(); animationController = AnimationController(duration: widget.duration, vsync: this); // 初始化第一段动画:位置1→位置2 slideAnimation = Tween<Offset>(begin: const Offset(1.0, 0), end: const Offset(0.0, 0)).animate(animationController); opacityAnimation = Tween<double>(begin: 1.0, end: 1.0).animate(animationController); // 监听第一段动画完成事件 animationController.addStatusListener((status) async { if (status == AnimationStatus.completed) { // 等待指定时长 await Future.delayed(const Duration(seconds: 2)); // 重置控制器,配置第二段动画:位置2→位置3+消失 setState(() { animationController.reset(); animationController.duration = const Duration(seconds: 1); slideAnimation = Tween<Offset>(begin: const Offset(0.0, 0), end: const Offset(-1.0, 0)).animate(animationController); opacityAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(animationController); }); // 启动第二段动画 animationController.forward(); } }); } @override Widget build(BuildContext context) { return GestureDetector( onTap: () { animationController.forward(from: 0); }, child: FadeTransition( opacity: opacityAnimation, child: SlideTransition( position: slideAnimation, child: getBarrageWidget(), ), ), ); } @override void dispose() { animationController.dispose(); super.dispose(); } Widget getBarrageWidget() { return Container( width: 100, height: 50, color: Colors.blue, child: const Center(child: Text("弹幕")), ); } }
内容的提问来源于stack exchange,提问作者GHH
相关产品推荐
相关产品推荐

