如何基于已有数据创建Flutter填充式进度条容器
实现带进度背景的列表组件
首先先把你的数据结构小问题修正下,原来的programStepCounts初始化写错了,得用StepProgress的构造函数创建实例,不然跑不起来:
final Map<ProgressKeys, StepProgress> programStepCounts = { ProgressKeys.articles: StepProgress( displayText: "Articles Read", progress: 2, count: 4, ), ProgressKeys.meals: StepProgress( displayText: "Meals Logged", progress: 3, count: 9, ), // 其他项照着补就行 };
接下来实现核心的进度列表项,咱们用Stack来叠背景和文字,这样就能做出左边填充颜色的效果。直接上代码:
// 单个进度项组件 class ProgressListItem extends StatelessWidget { final StepProgress progress; const ProgressListItem({super.key, required this.progress}); @override Widget build(BuildContext context) { // 算一下进度占比,比如2/4就是0.5,用来控制背景宽度 final progressRatio = progress.progress / progress.count; return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Container( height: 60, // 外层灰色背景+圆角 decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(8), ), child: Stack( children: [ // 进度填充的蓝色背景 ClipRRect( borderRadius: BorderRadius.circular(8), // 宽度按比例来,减去左右的padding,刚好填满外层容器的有效宽度 child: Container( width: (MediaQuery.of(context).size.width - 32) * progressRatio, color: Colors.blue[300], ), ), // 上面叠文字和进度数字 Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( progress.displayText, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500), ), Text( "${progress.progress}/${progress.count}", style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), ], ), ), ], ), ), ); } }
最后用你想到的ListView.builder把所有项渲染出来:
class ProgressScreen extends StatelessWidget { const ProgressScreen({super.key}); @override Widget build(BuildContext context) { // 把Map里的值转成列表,方便ListView遍历 final progressItems = programStepCounts.values.toList(); return Scaffold( appBar: AppBar(title: const Text("进度追踪")), body: ListView.builder( itemCount: progressItems.length, itemBuilder: (context, index) { return ProgressListItem(progress: progressItems[index]); }, ), ); } }
关键说明
Stack就是用来把多个组件叠在一起的,背景在底下,文字在上面,刚好符合需求。ClipRRect是为了让蓝色的进度背景和外层灰色容器的圆角保持一致,不然会露出直角,影响美观。- 进度比例计算很简单,已完成数除以总数,得到的比例用来控制背景宽度,就能实现随进度变化的填充效果。
你可以自己改颜色、圆角大小、容器高度这些参数,调成你想要的样子。
内容的提问来源于stack exchange,提问作者nyphur
相关产品推荐
相关产品推荐

