Flutter多Tween自动循环动画实现:解决跳变问题
解决Flutter多属性自动循环Tween动画跳变问题
问题说明
需要实现容器的height、width、color三个属性自动循环平滑过渡的动画,但当前代码中容器属性直接取Tween的begin值,导致动画在随机值间跳变,无法实现平滑过渡效果。
错误原因
- 未利用AnimationController的进度值对Tween进行插值计算,直接使用Tween的
begin属性,跳过了动画过渡过程 - 使用
addListener判断动画完成状态,不如addStatusListener精准 - 未通过Tween的
lerp方法根据动画进度获取当前过渡值
修正后的完整代码
import 'dart:math'; import 'package:flutter/material.dart'; class AnimatedSquare extends StatefulWidget { const AnimatedSquare({super.key}); @override State<AnimatedSquare> createState() => _AnimatedSquareState(); } class _AnimatedSquareState extends State<AnimatedSquare> with SingleTickerProviderStateMixin { late final AnimationController controller; late Tween<double> containerWidth; late Tween<double> containerHeight; late Tween<Color> containerColor; final Random random = Random(); @override void initState() { super.initState(); controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 800), ); // 初始化初始Tween值 containerWidth = Tween<double>( begin: 250, end: random.nextInt(300).toDouble(), ); containerHeight = Tween<double>( begin: 250, end: random.nextInt(300).toDouble(), ); containerColor = Tween<Color>( begin: Colors.red, end: Color.fromRGBO( random.nextInt(255), random.nextInt(255), random.nextInt(255), 1, ), ); // 监听动画状态,完成后触发下一轮动画 controller.addStatusListener((status) { if (status == AnimationStatus.completed) { setNewValues(); controller.forward(); } }); controller.forward(); } void setNewValues() { // 将当前结束值设为下一轮的起始值 containerWidth.begin = containerWidth.end; containerHeight.begin = containerHeight.end; containerColor.begin = containerColor.end; // 重置控制器,准备新的动画 controller.reset(); // 设置新的随机结束值 containerWidth.end = random.nextInt(300).toDouble(); containerHeight.end = random.nextInt(300).toDouble(); containerColor.end = Color.fromRGBO( random.nextInt(255), random.nextInt(255), random.nextInt(255), 1, ); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: controller, builder: (context, child) { return Container( // 根据动画进度获取Tween插值后的当前值 height: containerHeight.lerp(controller.value), width: containerWidth.lerp(controller.value), decoration: BoxDecoration( color: containerColor.lerp(controller.value), ), ); }, ); } @override void dispose() { controller.dispose(); super.dispose(); } }
关键修改点说明
- 动画值计算:在
AnimatedBuilder的builder方法中,使用Tween.lerp(controller.value)获取当前动画进度对应的属性值,实现平滑过渡 - 状态监听优化:改用
addStatusListener监听动画完成状态,比addListener更精准可靠 - 初始化顺序调整:将
super.initState()移到初始化控制器之前,符合Flutter生命周期规范 - 代码规范:给
Random变量添加final修饰符,提升代码可读性
内容的提问来源于stack exchange,提问作者Santiago G
相关产品推荐
相关产品推荐

