如何创建闪烁红色圆形?Flutter实现方案求助
实现闪烁红色圆形的最佳方案
先说说你现有代码的问题
- 你只传了一个
Container作为children,但你的BlinkWidget逻辑是切换不同子组件,只有一个子组件时完全不会有视觉变化 - 你的
Container没设置宽高,默认尺寸为0,自然看不到红色区域 - 你的实现逻辑和SVG的透明度渐变动画不符,SVG是通过改变opacity实现闪烁,而你是切换组件
方案一:用AnimatedOpacity实现(最简单直接)
这是最省心的方式,直接利用Flutter自带组件实现透明度循环变化,效果和SVG一致:
class BlinkingCircle extends StatefulWidget { const BlinkingCircle({Key? key}) : super(key: key); @override State<BlinkingCircle> createState() => _BlinkingCircleState(); } class _BlinkingCircleState extends State<BlinkingCircle> with SingleTickerProviderStateMixin { bool _isVisible = true; @override void initState() { super.initState(); // 1秒循环一次,对应SVG的dur="1s" Timer.periodic(const Duration(seconds: 1), (timer) { setState(() { _isVisible = !_isVisible; }); }); } @override Widget build(BuildContext context) { return AnimatedOpacity( opacity: _isVisible ? 1.0 : 0.0, duration: const Duration(milliseconds: 500), // 半秒完成透明度过渡,对应SVG的0→1→0变化 child: Container( width: 24, // 对应SVG的r=12,直径24 height: 24, decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), ), ); } }
方案二:用AnimationController+Opacity实现精细控制
如果要完全贴合SVG的values="0;1;0"三段式动画,可以用TweenSequence实现更精准的透明度变化:
class BlinkingCircle extends StatefulWidget { const BlinkingCircle({Key? key}) : super(key: key); @override State<BlinkingCircle> createState() => _BlinkingCircleState(); } class _BlinkingCircleState extends State<BlinkingCircle> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _opacityAnimation; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(seconds: 1), // 和SVG的dur="1s"保持一致 vsync: this, )..repeat(); // 无限重复动画 // 模拟SVG的0→1→0透明度变化 _opacityAnimation = TweenSequence([ TweenSequenceItem(tween: Tween<double>(begin: 0, end: 1), weight: 1), TweenSequenceItem(tween: Tween<double>(begin: 1, end: 0), weight: 1), ]).animate(_controller); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Opacity( opacity: _opacityAnimation.value, child: Container( width: 24, height: 24, decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), ), ); } }
修复你原有代码的版本
如果想保留自己的BlinkWidget,需要做以下调整:
// 调用方式,必须传至少两个子组件 BlinkWidget( children: [ Container( width: 24, height: 24, decoration: const BoxDecoration(color: Colors.red, shape: BoxShape.circle), ), const SizedBox(width: 24, height: 24), // 透明占位组件 ], ) // 修改后的BlinkWidget class BlinkWidget extends StatefulWidget { final List<Widget> children; final int interval; const BlinkWidget({required this.children, this.interval = 500, Key? key}) : super(key: key); @override _BlinkWidgetState createState() => _BlinkWidgetState(); } class _BlinkWidgetState extends State<BlinkWidget> with SingleTickerProviderStateMixin { late AnimationController _controller; int _currentWidget = 0; @override void initState() { super.initState(); _controller = AnimationController( duration: Duration(milliseconds: widget.interval), vsync: this, ); _controller.addStatusListener((status) { if (status == AnimationStatus.completed) { setState(() { _currentWidget = (_currentWidget + 1) % widget.children.length; }); _controller.forward(from: 0.0); } }); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return widget.children[_currentWidget]; } }
内容的提问来源于stack exchange,提问作者Test
相关产品推荐
相关产品推荐

