如何在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(), ), )); }
关键逻辑说明
- 状态管理:使用
StatefulWidget维护进度值、计时器实例和运行状态,确保UI能实时响应状态变化 - 进度驱动:通过
Timer.periodic定时更新进度值,结合TweenAnimationBuilder实现进度变化的平滑过渡,避免生硬跳变 - 停止功能:点击停止按钮时,立即取消计时器,并重置进度状态(如需保留当前进度,可删除
_progress = 0.0这行代码) - 内存安全:在组件销毁时主动取消计时器,避免内存泄漏
内容的提问来源于stack exchange,提问作者AkandeLoveth
相关产品推荐
相关产品推荐

