You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建闪烁红色圆形?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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 17:17:29