I'm building 'What to Do list' app, I made my own class Bucket(String, String, bool). 3rd property bool plays a role in checking if this task has done. I designed if bool is false, unfulfilled task get fontweight.bold and icon is shown red, and if bool is true, fulfilled task get fontweight.normal and icons is shown green. But, as soon as bool get 'true', it turns in to 'false', spontaneously. No other codes are designed to get bool changed. I don't understand why :(
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Homepage(),
);
}
}
class Homepage extends StatefulWidget {
Homepage({Key? key}) : super(key: key);
@override
State<Homepage> createState() => _HomepageState();
}
class _HomepageState extends State<Homepage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('WhattoDo List')),
floatingActionButton: IconButton(
onPressed: () async {
Bucket newbucket = await Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => PopUp()));
setState(() {
bucketlist.add(newbucket);
});
},
icon: Icon(Icons.add)),
body: bucketlist.isEmpty
? Center(child: Text('List is empty'))
: ListView.builder(
itemCount: bucketlist.length,
itemBuilder: (BuildContext context, int index) {
bool donecheck = bucketlist[index].isDone;
print(donecheck);
return Container(
margin: EdgeInsets.only(top: 5),
padding: EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.teal[200],
borderRadius: BorderRadius.circular(8)),
child: ListTile(
title: Text(
bucketlist[index].whattodo,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
decoration: donecheck
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text(
bucketlist[index].deadline,
style: TextStyle(fontSize: 15),
),
trailing: IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Wanna remove?"),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("Cancel"),
),
TextButton(
onPressed: () {
Navigator.pop(context);
setState(() {
bucketlist.removeAt(index);
});
},
child: Text(
"OK",
style: TextStyle(color: Colors.pink),
),
),
],
);
},
);
},
icon: Icon(Icons.delete)),
leading: IconButton(
onPressed: () {
setState(() {
donecheck = !donecheck;
print(donecheck);
});
},
icon: Icon(
Icons.check,
color: donecheck ? Colors.green : Colors.red,
)),
));
}));
}
}
class Bucket {
String whattodo;
String deadline;
bool isDone;
Bucket(this.whattodo, this.deadline, this.isDone);
}
List<Bucket> bucketlist = [];
class PopUp extends StatefulWidget {
const PopUp({Key? key}) : super(key: key);
@override
State<PopUp> createState() => _PopUpState();
}
class _PopUpState extends State<PopUp> {
TextEditingController textController = TextEditingController();
TextEditingController textController2 = TextEditingController();
String? errorshowingtext;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10), color: Colors.blue[200]),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: 150,
),
Text(
'Write down your task',
style: TextStyle(
fontSize: 25,
color: Colors.black,
fontWeight: FontWeight.normal),
),
SizedBox(
height: 25,
),
TextField(
autofocus: true,
decoration: InputDecoration(
hintText: 'What to Do', errorText: errorshowingtext),
style: TextStyle(fontSize: 22),
controller: textController,
),
TextField(
autofocus: true,
decoration: InputDecoration(
hintText: 'Deadline', errorText: errorshowingtext),
style: TextStyle(fontSize: 22),
controller: textController2,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
child: Text('OK'),
onPressed: () {
String? job = textController.text;
String? line = textController2.text;
Bucket newbucket = Bucket(job, line, false);
if (job.isNotEmpty && line.isNotEmpty) {
setState(() {
Navigator.pop(context, newbucket);
});
} else {
setState(() {
errorshowingtext = 'contents missing';
});
}
},
),
SizedBox(
width: 150,
),
ElevatedButton(
child: Text('Cancel'),
onPressed: () {
Navigator.pop(context);
},
),
],
)
],
),
),
);
}
}
CodePudding user response:
You already have isDone
to check the state. Your current method doesn't update the item check status, I prefer this way
class Bucket {
final String whattodo;
final String deadline;
final bool isDone;
Bucket({
required this.whattodo,
required this.deadline,
required this.isDone,
});
Bucket copyWith({
String? whattodo,
String? deadline,
bool? isDone,
}) {
return Bucket(
whattodo: whattodo ?? this.whattodo,
deadline: deadline ?? this.deadline,
isDone: isDone ?? this.isDone,
);
}
}
And the widget
class Homepage extends StatefulWidget {
const Homepage({Key? key}) : super(key: key);
@override
State<Homepage> createState() => _HomepageState();
}
class _HomepageState extends State<Homepage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('WhattoDo List')),
floatingActionButton: IconButton(
onPressed: () async {
Bucket newbucket = await Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => PopUp()));
setState(() {
bucketlist.add(newbucket);
});
},
icon: Icon(Icons.add)),
body: bucketlist.isEmpty
? Center(child: Text('List is empty'))
: ListView.builder(
itemCount: bucketlist.length,
itemBuilder: (BuildContext context, int index) {
return Container(
margin: EdgeInsets.only(top: 5),
padding: EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.teal[200],
borderRadius: BorderRadius.circular(8)),
child: ListTile(
title: Text(
bucketlist[index].whattodo,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
decoration: bucketlist[index].isDone
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text(
bucketlist[index].deadline,
style: TextStyle(fontSize: 15),
),
trailing: IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Wanna remove?"),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("Cancel"),
),
TextButton(
onPressed: () {
Navigator.pop(context);
setState(() {
bucketlist.removeAt(index);
});
},
child: Text(
"OK",
style: TextStyle(color: Colors.pink),
),
),
],
);
},
);
},
icon: Icon(Icons.delete)),
leading: IconButton(
onPressed: () {
setState(() {
bucketlist[index] = bucketlist[index]
.copyWith(isDone: !bucketlist[index].isDone);
});
},
icon: Icon(
Icons.check,
color: bucketlist[index].isDone
? Colors.green
: Colors.red,
)),
));
},
),
);
}
}
CodePudding user response:
you have to update the list todo value. not the Widget of Listile value.
change this
leading: IconButton(
onPressed: () {
setState(() {
// your code: donecheck = !donecheck;
bucketlist[index].isDone = !donecheck; // change to this
print(donecheck);
});
},