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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 12:45:04