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

如何让CircularProgressIndicator运行流畅并添加边缘动态光晕效果

代码修改实现

首先需要给你的State类混入动画支持:

class YourTimerPageState extends State<YourTimerPage> with SingleTickerProviderStateMixin {

替换你原来的变量和相关方法即可:

final int maxSeconds = 900;
  late int seconds = maxSeconds;
  Timer? timer;
  // 新增:进度平滑动画控制器
  late AnimationController _progressAnimController;
  // 新增:光晕缩放动画控制器
  late AnimationController _glowAnimController;
  late Animation<double> _glowScaleAnim;

  @override
  void initState() {
    super.initState();
    // 初始化进度动画控制器,时长和总计时时长一致
    _progressAnimController = AnimationController(
      vsync: this,
      duration: Duration(seconds: maxSeconds),
    );
    // 初始化光晕动画,2秒完成一次缩放循环,反向播放实现放大缩小往复
    _glowAnimController = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 2),
    )..repeat(reverse: true);
    _glowScaleAnim = Tween<double>(begin: 1.0, end: 1.1).animate(
      CurvedAnimation(parent: _glowAnimController, curve: Curves.easeInOut),
    );
  }

  @override
  void dispose() {
    _progressAnimController.dispose();
    _glowAnimController.dispose();
    timer?.cancel();
    super.dispose();
  }

  void resetTimer() {
    setState(() => seconds = maxSeconds);
    _progressAnimController.reset();
    timer = null;
  }

  void stopTimer({bool reset = true}) {
    timer?.cancel();
    _progressAnimController.stop();
    if (reset) {
      resetTimer();
    }
  }

  void startTimer({bool reset = true}) {
    if (reset) {
      resetTimer();
    }
    // 启动进度平滑动画
    _progressAnimController.forward(from: seconds / maxSeconds);
    // 启动秒数更新定时器
    timer = Timer.periodic(const Duration(seconds: 1), (_) {
      if (!mounted) return;
      if (seconds > 0) {
        setState(() => seconds--);
      } else {
        stopTimer(reset: false);
      }
    });
  }

  Widget buildTimer() => SizedBox(
    width: 200,
    height: 200,
    child: Stack(
      fit: StackFit.expand,
      children: [
        // 新增:光晕层
        ScaleTransition(
          scale: _glowScaleAnim,
          child: Container(
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              boxShadow: [
                BoxShadow(
                  color: Colors.white.withOpacity(0.6),
                  blurRadius: 20,
                  spreadRadius: 8,
                ),
              ],
            ),
            child: CircularProgressIndicator(
              value: _progressAnimController.value,
              valueColor: AlwaysStoppedAnimation(Colors.white.withOpacity(0.3)),
              strokeWidth: 12,
              backgroundColor: Colors.transparent,
            ),
          ),
        ),
        // 原有进度条
        CircularProgressIndicator(
          value: _progressAnimController.value,
          valueColor: const AlwaysStoppedAnimation(Colors.white),
          strokeWidth: 12,
          backgroundColor: Colors.greenAccent,
        ),
        GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTap: () {
            if (timer == null) {
              HapticFeedback.heavyImpact();
              startTimer(reset: seconds == maxSeconds);
            } else {
              stopTimer(reset: false);
            }
          },
          child: Center(child: buildTime()),
        ),
      ],
    ),
  );

效果说明

  • 进度条通过动画控制器的插值计算实现60fps的流畅过渡,不会再出现每秒跳变的情况
  • 光晕层绑定了循环缩放动画,会始终保持略微放大再缩小的呼吸效果,模糊半径和缩放比例可以自行调整BoxShadow的参数和Tween的起止值适配需求

内容的提问来源于stack exchange,提问作者Bn Minki

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 13:36:05