Flutter实现容器自动循环切换RGB颜色(类LED灯效果)
解决Flutter自动切换LED灯颜色动画的问题
问题根源
你当前的代码里,_changeColor()只在initState中执行了一次,后续Timer触发start++时并没有重新计算颜色值,所以容器颜色不会跟着更新。
修复方案(基于Timer)
直接在Timer的回调里更新颜色,确保每次start变化时同步计算并更新颜色:
import 'dart:async'; import 'package:flutter/material.dart'; class LedColorSwitcher extends StatefulWidget { const LedColorSwitcher({super.key}); @override State<LedColorSwitcher> createState() => _LedColorSwitcherState(); } class _LedColorSwitcherState extends State<LedColorSwitcher> { late Timer timer; int start = 0; Color changingColor = Colors.green; // 初始颜色 void startTimer() { const oneSec = Duration(seconds: 1); timer = Timer.periodic(oneSec, (Timer timer) { setState(() { start++; // 每次更新start后直接计算颜色 if (start % 3 == 0) { changingColor = Colors.green; } else if (start % 3 == 1) { changingColor = Colors.blue; } else { changingColor = Colors.red; } }); }); } @override void initState() { super.initState(); startTimer(); } @override void dispose() { timer.cancel(); // 销毁Timer,避免内存泄漏 super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Center( // 使用AnimatedContainer实现平滑颜色过渡 child: AnimatedContainer( duration: const Duration(milliseconds: 300), width: 100, height: 100, decoration: BoxDecoration( color: changingColor, shape: BoxShape.circle, ), ), ), ); } }
关键改进点
- 移除单独的
_changeColor方法,在Timer回调内直接更新颜色,确保start变化时同步触发颜色计算 - 添加
dispose方法销毁Timer,防止页面销毁后Timer持续运行导致内存泄漏 - 保留
AnimatedContainer的duration属性,实现颜色切换的平滑过渡效果
替代方案(使用AnimationController)
如果希望更贴合Flutter原生动画体系,可使用AnimationController实现,支持自定义过渡曲线与更灵活的动画控制:
import 'package:flutter/material.dart'; class LedColorSwitcher extends StatefulWidget { const LedColorSwitcher({super.key}); @override State<LedColorSwitcher> createState() => _LedColorSwitcherState(); } class _LedColorSwitcherState extends State<LedColorSwitcher> with SingleTickerProviderStateMixin { late AnimationController _controller; final List<Color> _colors = [Colors.green, Colors.blue, Colors.red]; int _currentColorIndex = 0; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(milliseconds: 300), vsync: this, )..addStatusListener((status) { if (status == AnimationStatus.completed) { // 动画完成后延迟1秒切换下一个颜色 Future.delayed(const Duration(seconds: 1), () { setState(() { _currentColorIndex = (_currentColorIndex + 1) % _colors.length; }); _controller.forward(from: 0); }); } }); // 启动初始动画 _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: AnimatedBuilder( animation: _controller, builder: (context, child) { return Container( width: 100, height: 100, decoration: BoxDecoration( color: Color.lerp( _colors[_currentColorIndex], _colors[(_currentColorIndex + 1) % _colors.length], _controller.value, ), shape: BoxShape.circle, ), ); }, ), ), ); } }
方案优势
- 基于Flutter原生动画系统,支持自定义过渡曲线与动画时长
- 可扩展更多动画效果,比如亮度变化、缩放等
- 同样实现自动运行,无需用户触发
内容的提问来源于stack exchange,提问作者Aaditya Jagdale
相关产品推荐
相关产品推荐

