Flutter中点击Checkbox List后如何更新Circular Percentage Indicator
Flutter 环形进度指示器联动勾选清单实现方案
核心修改逻辑
你原有代码的问题在于:
- 每个勾选框都创建了独立的
CheckBoxState实例,没有复用全局定义的checklist状态源 - 勾选状态修改只用了
StatefulBuilder的局部刷新,没有触发父组件更新,导致环形进度条无法同步刷新
对应修改思路:
- 直接复用全局
checklist数组作为勾选状态的唯一数据源 - 勾选状态变更时触发父组件的
setState,同时统计已勾选数量重新计算进度:进度值 = 已勾选数量 / 4 - 优化百分比的整数显示,避免出现
.0小数后缀
完整修改后代码
import 'package:flutter/material.dart'; import 'package:percent_indicator/percent_indicator.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; // 这里替换为你自己的相关页面、实体类、常量导入即可 // import 'Attendance.dart'; // import 'DetailsForm.dart'; // import 'HomeScreen.dart'; // import 'Remarks.dart'; // import 'UserModel.dart'; // import 'Project.dart'; // import 'const.dart'; class ReportForm extends StatefulWidget { final int itemIndex; final Project project; const ReportForm({this.itemIndex, this.project}); @override State<ReportForm> createState() => _ReportFormState(); } class _ReportFormState extends State<ReportForm> { FirebaseFirestore _firebaseFirestore = FirebaseFirestore.instance; UserModel loggedInUser = UserModel(); double progress = 0.0; currentProgressColor() { if (progress >= 0.6 && progress < 0.8) { return Colors.red; } if(progress >= 0.8){ return Colors.green; } else{ return Colors.orange; } } final checklist = [ CheckBoxState(title: 'Attendance'), CheckBoxState(title: 'Equipment Used'), CheckBoxState(title: 'Work Performed'), CheckBoxState(title: 'Remarks'), ]; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Container( height: 650, width: 370, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(13), boxShadow: [ BoxShadow( offset: Offset(0, 1), blurRadius: 17, spreadRadius: -23, color: kShadowColor, ), ], ), child: Column( children: <Widget>[ SizedBox( height:40, ), CircularPercentIndicator( radius: 200.0, circularStrokeCap: CircularStrokeCap.round, lineWidth: 25.0, progressColor: currentProgressColor(), percent: progress, animation: true, animationDuration: 1500, center: Text("${(progress * 100).toInt()}%", style: TextStyle( fontSize: 30, ),), footer: Text("Daily Report Completion", style: TextStyle( fontSize: 15, color: Colors.green, ),),), SizedBox( height:20, ), StreamBuilder<QuerySnapshot>( stream: _firebaseFirestore.collection("Attendance").snapshots(), builder: (context, snapshot) { return GestureDetector( onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => Attendance( ), )); }, child: Card( clipBehavior: Clip.antiAlias, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(13.0) ), elevation: 10, margin: EdgeInsets.fromLTRB(10.0, 2.0, 10.0, 2.0), child: Container( color: Colors.white, width: 350, height:60, child: Padding( padding: const EdgeInsets.all(2.0), // 复用checklist数组内的实例,不要新建对象 child: buildSingleCheckbox(checklist[0]), ), ), ), ); } ), SizedBox( height:18, ), GestureDetector( onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => DetailsForm(project: widget.project, itemIndex: widget.itemIndex), )); }, child: Card( clipBehavior: Clip.antiAlias, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(13.0) ), elevation: 10, margin: EdgeInsets.fromLTRB(10.0, 2.0, 10.0, 2.0), child: Container( color: Colors.white, width: 350, height: 60, child: Padding( padding: const EdgeInsets.all(2.0), child: buildSingleCheckbox(checklist[1]), ), ), ), ), SizedBox( height:18, ), GestureDetector( onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => HomeScreen(), )); }, child: Card( clipBehavior: Clip.antiAlias, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(13.0) ), elevation: 10, margin: EdgeInsets.fromLTRB(10.0, 2.0, 10.0, 2.0), child: Container( color: Colors.white, width: 350, height: 60, child: Padding( padding: const EdgeInsets.all(2.0), child: buildSingleCheckbox(checklist[2]), ), ), ), ), SizedBox( height:18, ), GestureDetector( onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => Remarks(), )); }, child: Card( clipBehavior: Clip.antiAlias, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(13.0) ), elevation: 10, margin: EdgeInsets.fromLTRB(10.0, 2.0, 10.0, 2.0), child: Container( color: Colors.white, width: 350, height: 60, child: Padding( padding: const EdgeInsets.all(2.0), child: buildSingleCheckbox(checklist[3]), ), ), ), ), ], ), ), ); } // 去掉原有的StatefulBuilder,直接用父组件setState联动刷新 Widget buildSingleCheckbox(CheckBoxState checkbox) => CheckboxListTile( activeColor: Colors.green, value: checkbox.value, title: Text(checkbox.title), onChanged: (value) { setState(() { checkbox.value = value ?? false; // 统计已勾选数量计算最新进度 int checkedCount = checklist.where((item) => item.value).length; progress = checkedCount / 4; }); }, ); } class CheckBoxState{ final String title; bool value; CheckBoxState({ @required this.title, this.value = false,}); }
内容的提问来源于stack exchange,提问作者Adila
相关产品推荐
相关产品推荐

