I have a listview which contains checkbox inside the listTile. This listTile will be generated dynamically based on the length of the list. Here is my ListTile and Custom checkbox code.
ListTile(
leading: Container(
height: 30,
width: 42,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
"assets/images/ic_subtract.png"),
fit: BoxFit.fill)),
child: const Image(
image: AssetImage(
"assets/images/ic_dummy_project_icon.png"),
width: 24,
height: 24,
)),
title: Text(
eventTicketList[index]
.firstName
.toString(),
style: const TextStyle(
color: Color.fromRGBO(
26, 49, 60, 1),
fontWeight: FontWeight.w500,
fontSize: 16,
fontFamily: 'SF Pro Text')),
subtitle: loadTicketInfo(
eventTicketList, index),
trailing: loadCheckBox(isChecked))
loadCheckBox(bool isChecked) {
return CustomCheckbox(
value: isChecked,
onChanged: (value) {
setState(() {
isChecked = value!;
})
},
);
class CustomCheckbox extends StatefulWidget {
const CustomCheckbox({
required this.value,
Key? key,
this.width = 24.0,
this.height = 24.0,
this.color,
this.iconSize,
this.onChanged,
this.checkColor,
}) : super(key: key);
final double width;
final double height;
final Color? color;
final bool? value;
// Now you can set the checkmark size of your own
final double? iconSize;
final Color? checkColor;
final Function(bool?)? onChanged;
@override
State<CustomCheckbox> createState() => _CustomCheckboxState();
}
class _CustomCheckboxState extends State<CustomCheckbox> {
bool isChecked = false;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
setState(() => isChecked = !isChecked);
widget.onChanged?.call(isChecked);
},
child: Container(
width: widget.width,
height: widget.height,
child: isChecked
? Image(
image: AssetImage("assets/images/ic_checked.png"),
height: 24,
width: 24,
alignment: Alignment.topRight,
)
: Image(
image: AssetImage("assets/images/ic_selector.png"),
height: 24,
width: 24,
alignment: Alignment.topRight,
)
),
);
}
}
I want to select all the check box when i click the button and I also want to unselect all when I click the same button again. I have tried few examples from stackoverflow and from different other sources. But nothing works fine or I have not done that properly. Could someone help me to solve this problem?
Padding(
padding: EdgeInsets.only(right: 25),
child: TextButton(
child: const Text("Select All",
style: TextStyle(
fontSize: 16,
fontFamily: 'SF Pro Text',
fontWeight: FontWeight.w200,
color: Color.fromRGBO(
0, 94, 180, 1))),
onPressed: () {
//select all checkbox
}))
All you need to do is to override didUpdateWidget inside CustomCheckbox widget. Because CustomCheckBox widget is stateful widget, you don’t get it’s initState called multiple times to set isChecked
. DidUpdateWidget
gets called followed by build
method.
@override
void didUpdateWidget(covariant CustomCheckbox oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.value != oldWidget.value) {
isChecked = widget.value!;
}
}
Here is the full code which I tried
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _isAllChecked = false;
final List<String> _items = const [
'London',
'Paris',
'New York',
'Berlin',
'Madrid'
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Checkboxes'),
actions: [
Checkbox.adaptive(
value: _isAllChecked,
onChanged: (value) {
if (value == null) {
return;
}
setState(() {
_isAllChecked = value;
});
}),
],
),
body: ListView.builder(
itemBuilder: (context, index) {
return ListTile(
title: Text(
_items[index],
),
trailing: loadCheckBox(_isAllChecked));
},
itemCount: _items.length,
),
);
}
loadCheckBox(bool isChecked) {
return CustomCheckbox(
value: isChecked,
onChanged: (value) {
setState(() {
isChecked = value!;
});
},
);
}
}
class CustomCheckbox extends StatefulWidget {
const CustomCheckbox({
required this.value,
super.key,
this.width = 24.0,
this.height = 24.0,
this.color,
this.iconSize,
this.onChanged,
this.checkColor,
});
final double width;
final double height;
final Color? color;
final bool? value;
// Now you can set the checkmark size of your own
final double? iconSize;
final Color? checkColor;
final Function(bool?)? onChanged;
@override
State<CustomCheckbox> createState() => _CustomCheckboxState();
}
class _CustomCheckboxState extends State<CustomCheckbox> {
bool isChecked = false;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
setState(() => isChecked = !isChecked);
widget.onChanged?.call(isChecked);
},
child: SizedBox(
width: widget.width,
height: widget.height,
child: isChecked
? const Icon(Icons.check_box)
: const Icon(Icons.check_box_outline_blank),
),
);
}
@override
void didUpdateWidget(covariant CustomCheckbox oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.value != oldWidget.value) {
isChecked = widget.value!;
}
}
}