我有一个列表视图,其中包含 listTile 内的复选框。这个listTile将根据列表的长度动态生成。这是我的 ListTile 和自定义复选框代码。
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,
)
),
);
}
}
我想在单击按钮时选择所有复选框,并且在再次单击同一按钮时取消选择所有复选框。我尝试了来自 stackoverflow 和其他不同来源的一些示例。但没有任何效果,或者我没有正确地做到这一点。有人可以帮我解决这个问题吗?
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
}))
您需要做的就是覆盖 CustomCheckbox 小部件内的 didUpdateWidget。因为 CustomCheckBox 小部件是有状态小部件,所以您不会多次调用它的 initState 来设置
isChecked
。 DidUpdateWidget
被调用,然后是 build
方法。
@override
void didUpdateWidget(covariant CustomCheckbox oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.value != oldWidget.value) {
isChecked = widget.value!;
}
}
这是我尝试过的完整代码
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!;
}
}
}