如何用Flutter实现自定义进度指示器?解决页面切换加载异常问题
自定义进度指示器实现方案
你要的环形进度带文字的效果,可以通过Stack结合CircularProgressIndicator快速实现,也可以用CustomPaint做更个性化的定制,以下是两种可行方案:
方案1:基础环形进度+文字(快速实现)
import 'package:flutter/material.dart'; class CustomProgress extends StatelessWidget { final double progress; // 0-1的进度值 final String label; const CustomProgress({ super.key, required this.progress, required this.label, }); @override Widget build(BuildContext context) { return Stack( alignment: Alignment.center, children: [ // 灰色背景圆环 SizedBox( width: 100, height: 100, child: CircularProgressIndicator( value: 1, strokeWidth: 8, valueColor: AlwaysStoppedAnimation(Colors.grey.shade300), ), ), // 彩色进度圆环 SizedBox( width: 100, height: 100, child: CircularProgressIndicator( value: progress, strokeWidth: 8, valueColor: AlwaysStoppedAnimation(Colors.blue), ), ), // 中心进度文字 Text( label, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), ], ); } } // 使用示例 class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('进度指示器示例')), body: const Center( child: CustomProgress(progress: 0.7, label: '70%'), ), ); } }
方案2:渐变环形进度(进阶定制)
如果需要渐变效果,用ShaderMask包装进度圆环即可:
ShaderMask( shaderCallback: (Rect bounds) { return const LinearGradient( colors: [Colors.blue, Colors.green], begin: Alignment.topLeft, end: Alignment.bottomRight, ).createShader(bounds); }, child: SizedBox( width: 100, height: 100, child: CircularProgressIndicator( value: progress, strokeWidth: 8, valueColor: const AlwaysStoppedAnimation(Colors.white), ), ), )
页面切换后首页无法加载问题解决
你遇到的页面切换后首页失效问题,核心是页面状态未正确维护或进度指示器的状态持有导致页面无法重建,可通过以下两种方式修复:
- 用
AutomaticKeepAliveClientMixin保持页面状态
如果首页是StatefulWidget,混入该mixin可避免页面切换时被销毁重建:
class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive => true; @override Widget build(BuildContext context) { super.build(context); // 必须调用super.build return Scaffold( // 首页内容(包含进度指示器) ); } }
- 重置进度状态
确保页面返回时重置进度相关变量,避免状态残留:
@override void initState() { super.initState(); // 初始化/重置进度值 _currentProgress = 0; } @override void didChangeDependencies() { super.didChangeDependencies(); // 页面返回时重新加载数据 _fetchData(); }
另外检查是否错误使用全局状态持有进度数据,尽量将进度状态放在页面局部状态中,避免影响页面重建逻辑。
内容的提问来源于stack exchange,提问作者Ahmed Salavy
相关产品推荐
相关产品推荐

