I have a simple todo app that allows info input into the text field to show up in a list.
However, when I want to tick off an item in the list, instead of ticking that one item, it ticks them all. How do I fix this?
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: const TodoApp(),
theme: ThemeData(primarySwatch: Colors.yellow),
));
}
class TodoApp extends StatefulWidget {
const TodoApp({super.key});
@override
State<TodoApp> createState() => _TodoAppState();
}
class _TodoAppState extends State<TodoApp> {
final _textyController = TextEditingController();
List<String> storedText = [];
bool checkedValue = false;
@override
Widget build(context) {
return Scaffold(
backgroundColor: Colors.yellow[100],
appBar: AppBar(
title: const Text("Todo"),
centerTitle: true,
elevation: 0,
),
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 15.0),
child: Column(
children: [
Expanded(
//
// LIST STARTS
//
child: ListView.builder(
reverse: true,
itemCount: storedText.length,
//LEARN: UNDERSTAND THIS
itemBuilder: (context, index) {
//
//{STYLING} LIST TILE STARTS
//
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.yellow),
child: Padding(
padding: const EdgeInsets.all(8.0),
//
//LIST TILE STARTS
//
child: CheckboxListTile(
activeColor: Colors.black,
controlAffinity: ListTileControlAffinity.leading,
//LEARN: UNDERSTAND THIS
title: Text(storedText[index]),
value: checkedValue,
onChanged: (newCheckedValue) {
setState(() {
checkedValue = newCheckedValue!;
});
}),
),
),
);
},
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 20.0),
child: TextField(
controller: _textyController,
onSubmitted: (value) {
setState(() {
//LEARN: UNDERSTAND THIS
storedText.insert(0, value);
_textyController.clear();
});
},
decoration: const InputDecoration(
labelText: '+ Add a task',
labelStyle: TextStyle(
color: Colors.grey,
),
border: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
focusColor: Colors.blue,
),
cursorColor: Colors.grey[400],
),
),
],
)),
);
}
}
I think it might be something do with KEYS, but im not sure? (my next stage is to make this into a ‘Reorderable List’ so I will likely need keys at that point too.
Im completely new to flutter (and programming in general), so if youre able to also explain why, that would be ideal.
2
Answers
You have a single variable in your widgets state:
In your list, you’re using (and setting) that same variable for every item in the list. You need to store a flag for each item, perhaps by changing your
storedText
list fromStrings
to a new class that can store both the text and the checked state (or instead of a class you could use records, likeList<(String, bool)>
– which is a list of String/bool pairs).Make the following changes:
1. Add a new list of
itemChecked
to keep track of the checked state for each task in the list.Replace
with
2. In the
CheckboxListTile
, update the value property. Now, it checks theitemChecked
list to determine whether a task is checked or not.Replace
with
3. on click item,
onChanged
callback of theCheckboxListTile
, update theitemChecked
list with the new checked value for the specific task.Replace
with
4. On submitting an item using
onSubmitted
callback of the TextField, you already add a new task to thestoredText
list, also add state for the item is not checked. Add code afterstoredText.insert(0, value);
Here is the updated code:
Here is the expected result:
Preview Link: https://dartpad.dev/?id=426729548698c392334a758d7dbc1899