带有controller的自定义组件——列表勾选删除
前言
在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;const CustomComponent({super.key,required this.controller,required this.itemBuilder,required this.itemCount});@overrideState<StatefulWidget> createState() => _CustomComponentState();
}class _CustomComponentState extends State<CustomComponent> {@overridevoid initState() {super.initState();/// 监听数据变化widget.controller.addListener(() {setState(() {});debugPrint("列表改变了:${widget.controller.valueList}");});/// 初始化每一个勾选框的值widget.controller.clear();widget.controller.init(widget.itemCount);}@overrideWidget 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": "王五"},];@overrideWidget 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),),);},))],));}
}