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

如何在Flutter中实现带停止按钮的圆形进度条:同步停止计时器与指示器

Flutter 带停止按钮的圆形进度条实现方案

直接基于你的需求,下面是完整的实现代码,包含进度条控制逻辑和停止按钮功能:

import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';

class CircularProgressWithStop extends StatefulWidget {
  const CircularProgressWithStop({super.key});

  @override
  State<CircularProgressWithStop> createState() => _CircularProgressWithStopState();
}

class _CircularProgressWithStopState extends State<CircularProgressWithStop> {
  double _progress = 0.0;
  Timer? _countdownTimer;
  bool _isRunning = false;
  // 可自定义总时长(秒)
  final int _totalDuration = 60;

  // 启动进度动画与计时器
  void _startProgress() {
    if (_isRunning) return;
    
    setState(() {
      _isRunning = true;
      _progress = 0.0;
    });

    // 每100ms更新一次进度,保证动画平滑
    _countdownTimer = Timer.periodic(const Duration(milliseconds: 100), (timer) {
      setState(() {
        // 计算每次更新的进度增量
        _progress += 0.1 / _totalDuration;
        // 进度满时自动停止
        if (_progress >= 1.0) {
          _stopProgress();
        }
      });
    });
  }

  // 停止进度动画与计时器
  void _stopProgress() {
    _countdownTimer?.cancel();
    setState(() {
      _isRunning = false;
      _progress = 0.0; // 也可保留当前进度,根据需求注释此行
    });
  }

  @override
  void dispose() {
    // 页面销毁时务必取消计时器,避免内存泄漏
    _countdownTimer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          // 圆形进度指示器(基于TweenAnimationBuilder实现平滑过渡)
          TweenAnimationBuilder(
            tween: Tween<double>(begin: 0.0, end: _progress),
            duration: const Duration(milliseconds: 100),
            builder: (context, value, child) {
              return Stack(
                alignment: Alignment.center,
                children: [
                  CircularProgressIndicator(
                    value: value,
                    strokeWidth: 8,
                    backgroundColor: Colors.grey.shade300,
                    valueColor: const AlwaysStoppedAnimation<Color>(Colors.blueAccent),
                  ),
                  // 中间显示剩余时间(可替换为百分比或其他内容)
                  Text(
                    '${(_totalDuration - (_totalDuration * value)).round()}s',
                    style: const TextStyle(
                      fontSize: 22,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                ],
              );
            },
          ),
          const SizedBox(height: 24),
          // 控制按钮(运行时显示停止,停止时显示开始)
          ElevatedButton(
            onPressed: _isRunning ? _stopProgress : _startProgress,
            style: ElevatedButton.styleFrom(
              padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
              backgroundColor: _isRunning ? Colors.redAccent : Colors.blueAccent,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(8),
              ),
            ),
            child: Text(
              _isRunning ? '停止' : '开始',
              style: const TextStyle(
                fontSize: 16,
                color: Colors.white,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// 可直接在主页面调用此组件
void main() {
  runApp(const MaterialApp(
    home: Scaffold(
      body: CircularProgressWithStop(),
    ),
  ));
}

关键逻辑说明

  1. 状态管理:使用StatefulWidget维护进度值、计时器实例和运行状态,确保UI能实时响应状态变化
  2. 进度驱动:通过Timer.periodic定时更新进度值,结合TweenAnimationBuilder实现进度变化的平滑过渡,避免生硬跳变
  3. 停止功能:点击停止按钮时,立即取消计时器,并重置进度状态(如需保留当前进度,可删除_progress = 0.0这行代码)
  4. 内存安全:在组件销毁时主动取消计时器,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 10:52:55