带有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;
   // 是否全选
  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),
                  ),
                );
              },
            ))
          ],
        ));
  }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无知的小菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值