I want to do the checklist section which have circular percentage indicator. The percentage should updated once the list of checklist(checkbox) is clicked. Each Checkbox should hold 25% because have 4 checklist and the overall percentage is 100. Please help me how to update the percentage.
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: new Text("${this.progress * 100}%", style: TextStyle(
fontSize: 30,
),),
footer: new 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),
child: buildSingleCheckbox(CheckBoxState(title: 'Attendance')),
),
),
),
);
}
),
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(CheckBoxState(title: 'Equipment Used')),
),
),
),
),
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(CheckBoxState(title: 'Work Performed')),
),
),
),
),
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(CheckBoxState(title: 'Remarks')),
),
),
),
),
],
),
),
);
}
Widget buildSingleCheckbox(CheckBoxState checkbox) => StatefulBuilder(
builder: (context, _setState) => CheckboxListTile(
activeColor: Colors.green,
value: checkbox.value,
title: Text(checkbox.title),
onChanged: (value) =>
_setState(() => checkbox.value = value),
),
);
}
class CheckBoxState{
final String title;
bool value;
CheckBoxState({
@required this.title,
this.value = false,});
}
CodePudding user response:
I did a small test you can apply according to your need
import 'package:flutter/material.dart';
import 'package:percent_indicator/circular_percent_indicator.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Teste',
debugShowCheckedModeBanner: false,
home: Teste(),
);
}
}
class Teste extends StatefulWidget {
const Teste({Key? key}) : super(key: key);
@override
_TesteState createState() => _TesteState();
}
class _TesteState extends State<Teste> {
List<bool> checkboxStatus = [];
double percentage = 0.0;
final checklist = ['Attendance', 'Equipment Used', 'Work Performed', 'Remarks'];
@override
void initState() {
super.initState();
checklist.forEach((element) => checkboxStatus.add(false));
}
currentProgressColor() {
if (percentage >= 0.6 && percentage < 0.8) {
return Colors.red;
}
if (percentage >= 0.8) {
return Colors.green;
} else {
return Colors.orange;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: 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: Colors.orange)],
),
child: Column(
children: <Widget>[
SizedBox(height: 40),
CircularPercentIndicator(
animateFromLastPercent: true,
radius: 200.0,
circularStrokeCap: CircularStrokeCap.round,
lineWidth: 25.0,
progressColor: currentProgressColor(),
percent: percentage,
animation: true,
animationDuration: 1500,
center: Text('${percentage * 100} %'),
footer: Text("Daily Report Completion", style: TextStyle(fontSize: 15, color: Colors.green)),
),
SizedBox(height: 20),
Expanded(
child: ListView.builder(
itemCount: checklist.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(13.0)),
elevation: 10,
child: ElevatedButton(
onPressed: () {
if (checklist[index] == 'Attendance') {
Navigator.push(context, MaterialPageRoute(builder: (context) => Attendance()));
} else if() {
/// other page
}
},
style: ElevatedButton.styleFrom(primary: Colors.white),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(checklist[index], style: TextStyle(color: Colors.black)),
Checkbox(
value: checkboxStatus[index],
onChanged: (value) {
if (checkboxStatus[index] == false) {
percentage = (1 / checklist.length);
} else {
percentage -= (1 / checklist.length);
}
setState(() => checkboxStatus[index] = !checkboxStatus[index]);
},
checkColor: Colors.white,
)
],
),
),
),
);
},
),
)
],
),
),
),
);
}
}