前言
在flutter以及第三方的组件中,好多都需要一个controller
值。
准备
创建控制器类
控制器类通常继承自 ChangeNotifier
,这样组件状态改变时可以通知外部监听者。
class CustomController extends ChangeNotifier {
/// 存放勾选框的值
final List<bool> _valueList = [];
/// 是否显示勾选框
bool _showCheckBox = false;
/// 获取当前的显示状态
bool get isShow => _showCheckBox;
/// 获取单个value的值
bool getValue(int index) => _valueList[index];
/// 获取勾选列表值
List<bool> get valueList => _valueList;
/// 修改状态
void change(int index) {
_valueList[index] = !_valueList[index];
notifyListeners();
}
/// 修改显示状态
void switchShow() {
_showCheckBox = !_showCheckBox;
notifyListeners();
}
/// 清空列表
void clear() {
_valueList.clear();
notifyListeners();
}
/// 全选
void selectAll() {
for (int i = 0; i < _valueList.length; i++) {
_valueList[i] = true;
}
notifyListeners();
}
/// 初始化列表
void init(int length) {
_valueList.clear();
_showCheckBox = false;
for (int i = 0; i < length; i++) {
_valueList.add(false);
}
notifyListeners();
}
}
创建自定义组件
在自定义组件中,使用控制器来管理状态,并暴露出方法以便外部访问。
class CustomComponent extends StatefulWidget {
// 控制器
final CustomController controller;
final IndexedWidgetBuilder itemBuilder;
final int itemCount;
// 是否全选
final Function(bool state) onSelectedAll;
const CustomComponent(
{super.key,
required this.controller,
required this.itemBuilder,
required this.itemCount,
required this.onSelectedAll});
@override
State<StatefulWidget> createState() => _CustomComponentState();
}
class _CustomComponentState extends State<CustomComponent> {
@override
void initState() {
super.initState();
/// 监听数据变化
widget.controller.addListener(() {
debugPrint("列表改变了:${widget.controller.valueList}");
// 判断是否全都是true
bool isAllTrue = widget.controller.valueList.every((element) => element);
widget.onSelectedAll(isAllTrue);
});
/// 初始化每一个勾选框的值
widget.controller.clear();
widget.controller.init(widget.itemCount);
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: widget.itemCount,
itemBuilder: (context, index) {
return Stack(
children: [
widget.itemBuilder(context, index),
widget.controller.isShow
? Positioned(
top: 10,
right: 50,
child: Checkbox(
shape: const CircleBorder(),
side: const BorderSide(color: Colors.white),
value: widget.controller.getValue(index),
onChanged: (value) {
widget.controller.change(index);
},
),
)
: const SizedBox()
],
);
});
}
}
外部访问控制器
在外部直接调用控制器暴露出的方法来改变组件的状态,而不需要直接修改组件内部的状态。
这个结构允许你灵活地创建自定义组件,并通过控制器来控制和访问组件的内部状态
class _MyHomePageState extends State<MyHomePage> {
CustomController controller = CustomController();
List<Map<String, String>> list = [
{"id": "1", "name": "张三"},
{"id": "2", "name": "李四"},
{"id": "3", "name": "王五"},
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Column(
children: [
ElevatedButton(
onPressed: () {
controller.switchShow();
setState(() {});
},
child: Text(controller.isShow ? "完成" : "管理")),
ElevatedButton(
onPressed: () {
List<bool> checkedList = controller.valueList;
List<String> idList = [];
for (int i = 0; i < checkedList.length; i++) {
if (checkedList[i]) {
idList.add(list[i]["id"]!);
// 移除列表
list.removeAt(i);
}
}
// 初始化勾选
controller.init(list.length);
// 移除掉旧的消息,避免快速点击后,每隔4秒弹出一个消息
ScaffoldMessenger.of(context).removeCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("删除了${idList.join(",")}"),
duration: const Duration(seconds: 4),
backgroundColor: Colors.orange,
));
setState(() {});
},
child: const Text("删除")),
const SizedBox(
height: 30,
),
Expanded(
child: CustomComponent(
controller: controller,
itemCount: list.length,
itemBuilder: (context, index) {
return Container(
margin: const EdgeInsets.all(10),
color: Colors.blue,
height: 100,
width: 300,
child: Text(
"${list[index]["name"]}",
style: const TextStyle(color: Colors.white),
),
);
},
))
],
));
}
}