You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何实现跨Stateful Widget的复选框全选/反选

Flutter 实现全选与列表项复选框联动(无第三方依赖)

核心思路:状态提升

由于全选框和列表项是独立的Stateful Widget,需将选中状态的控制权统一移到它们的共同父Widget,通过回调函数实现状态同步。

1. 在父Widget中统一管理状态

定义两个核心状态,负责全选状态和所有列表项的选中状态:

class ParentPage extends StatefulWidget {
  const ParentPage({super.key});

  @override
  State<ParentPage> createState() => _ParentPageState();
}

class _ParentPageState extends State<ParentPage> {
  // 模拟业务列表数据,替换为你的实际数据
  final List<String> _listItems = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];
  bool _isSelectAll = false;
  late List<bool> _itemCheckedStates;

  @override
  void initState() {
    super.initState();
    // 初始化所有列表项为未选中状态
    _itemCheckedStates = List.filled(_listItems.length, false);
  }

  // 后续逻辑方法写在此处
}

2. 改造全选Checkbox的回调逻辑

更新全选框的onChanged方法,点击时同步所有列表项的选中状态:

// 父Widget中构建全选Row的代码
Row(
  mainAxisAlignment: MainAxisAlignment.start,
  children: [
    Transform.scale(
      scale: 1.3,
      child: Checkbox(
        side: MaterialStateBorderSide.resolveWith(
          (Set<MaterialState> states) {
            if (states.contains(MaterialState.selected)) {
              return const BorderSide(width: 2, color: Color(0xff34495E));
            }
            return const BorderSide(width: 1, color: Color(0xffB0BEC1));
          },
        ),
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
        activeColor: const Color(0xff34495E),
        materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
        visualDensity: const VisualDensity(horizontal: -4, vertical: -4),
        value: _isSelectAll,
        onChanged: (value) {
          setState(() {
            _isSelectAll = value ?? false;
            // 同步所有列表项的选中状态与全选框一致
            _itemCheckedStates = List.filled(_listItems.length, _isSelectAll);
          });
        },
      ),
    ),
    const SizedBox(width: 10),
    Text(
      'Select all',
      style: GoogleFonts.poppins(
          color: Colors.black87, fontSize: 12, fontWeight: FontWeight.w400),
    ),
  ],
)

3. 改造列表项Widget,接收外部状态与回调

将列表项的选中状态改为从父Widget传入,同时添加回调函数通知父Widget更新状态:

// 改造后的列表项Widget
class ListItemWidget extends StatefulWidget {
  final String title;
  final bool isChecked;
  final ValueChanged<bool> onCheckedChanged;
  final bool isCheckboxVisible;

  const ListItemWidget({
    super.key,
    required this.title,
    required this.isChecked,
    required this.onCheckedChanged,
    required this.isCheckboxVisible,
  });

  @override
  State<ListItemWidget> createState() => _ListItemWidgetState();
}

class _ListItemWidgetState extends State<ListItemWidget> {
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(widget.title),
      leading: Visibility(
        visible: widget.isCheckboxVisible,
        child: Transform.scale(
          scale: 1.3,
          child: Checkbox(
            side: MaterialStateBorderSide.resolveWith(
              (Set<MaterialState> states) {
                if (states.contains(MaterialState.selected)) {
                  return const BorderSide(width: 2, color: Color(0xff34495E));
                }
                return const BorderSide(width: 1, color: Color(0xffB0BEC1));
              },
            ),
            shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
            activeColor: const Color(0xff34495E),
            value: widget.isChecked,
            onChanged: (value) {
              widget.onCheckedChanged(value ?? false);
            },
          ),
        ),
      ),
    );
  }
}

4. 在父Widget中构建列表,绑定状态与回调

在父Widget的build方法中构建列表,传递每个列表项的状态和回调,同时处理单个列表项点击后更新全选状态:

// 父Widget中构建列表的代码
ListView.builder(
  itemCount: _listItems.length,
  itemBuilder: (context, index) {
    return ListItemWidget(
      title: _listItems[index],
      isChecked: _itemCheckedStates[index],
      isCheckboxVisible: true, // 替换为你的controller.isCheboxVisible.value
      onCheckedChanged: (value) {
        setState(() {
          _itemCheckedStates[index] = value;
          // 检查所有列表项是否都选中,更新全选状态
          _isSelectAll = _itemCheckedStates.every((item) => item);
        });
      },
    );
  },
)

动态列表优化(可选)

如果列表数据是动态加载的(如分页),需在数据更新时同步更新选中状态列表:

// 更新列表数据时调用
void updateListData(List<String> newItems) {
  setState(() {
    _listItems = newItems;
    // 保留已有选中状态,新添加项默认未选中
    _itemCheckedStates = [
      ..._itemCheckedStates.take(newItems.length),
      ...List.filled(newItems.length - _itemCheckedStates.length, false)
    ];
    // 重新校验全选状态
    _isSelectAll = _itemCheckedStates.every((item) => item);
  });
}

内容的提问来源于stack exchange,提问作者tesseract

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:50:38