如何获取SegmentedButton多选模式下的最后选中值?并实现特定选中逻辑
需求说明
需要给启用多选的SegmentedButton实现两个约束逻辑:
- 前两个选项(索引0、1)不能同时被选中
- 选中最后一个选项(索引3)时,自动取消并禁用其他所有选项
核心思路
由于SegmentedButton的onSelectionChanged返回的是完整选中集合,无法直接拿到用户最新操作的选项,所以第一步要通过新旧选中集合的差集定位用户的操作:
- 若新集合比旧集合多一个元素,说明用户选中了该元素
- 若新集合比旧集合少一个元素,说明用户取消了该元素
拿到最新操作的选项后,再针对性应用规则:
- 操作对象是索引3:强制选中集合只保留3,同时禁用其他选项
- 操作对象是0或1:检查是否会导致0和1同时被选中,若是则只保留最新选中的那个
- 其他场景正常处理,但要确保已选中3时,其他选项无法被操作
修改后的完整代码
import 'package:flutter/material.dart'; class MyTestSelectedButton extends StatefulWidget { const MyTestSelectedButton({super.key}); @override State<MyTestSelectedButton> createState() => _MyTestSelectedButtonState(); } class _MyTestSelectedButtonState extends State<MyTestSelectedButton> { Set<int> selectedValues = {1}; @override Widget build(BuildContext context) { // 判断是否选中了最后一个选项 final isLastSelected = selectedValues.contains(3); // 前两个选项的禁用逻辑:选中3时全部禁用;未选中3时,选中其中一个则禁用另一个 final disableOption0 = isLastSelected || selectedValues.contains(1); final disableOption1 = isLastSelected || selectedValues.contains(0); // 选项2的禁用逻辑:选中3时禁用 final disableOption2 = isLastSelected; return Scaffold( body: Center( child: SegmentedButton( multiSelectionEnabled: true, style: ButtonStyle(visualDensity: VisualDensity(vertical: -4)), showSelectedIcon: false, segments: [ ButtonSegment( value: 0, label: const Text('0'), enabled: !disableOption0, ), ButtonSegment( value: 1, label: const Text('1'), enabled: !disableOption1, ), ButtonSegment( value: 2, label: const Text('2'), enabled: !disableOption2, ), const ButtonSegment( value: 3, label: Text('3'), ), ], selected: selectedValues, onSelectionChanged: (newSelectedValues) { setState(() { // 计算新旧集合的差集,定位用户最新操作的选项 final added = newSelectedValues.difference(selectedValues); final removed = selectedValues.difference(newSelectedValues); if (added.isNotEmpty) { final latestSelected = added.first; if (latestSelected == 3) { // 选中最后一个选项,强制只保留它 selectedValues = {3}; } else if (latestSelected == 0 || latestSelected == 1) { // 选中前两个之一,确保不同时选中 selectedValues = {latestSelected}; // 若之前选中了选项2,保留该选中状态(可根据需求调整) if (selectedValues.contains(2)) { selectedValues.add(latestSelected); } } else { // 选中选项2且未选中3时,正常更新选中集合 if (!isLastSelected) { selectedValues = newSelectedValues; } } } else if (removed.isNotEmpty) { final latestRemoved = removed.first; if (latestRemoved == 3) { // 取消选中最后一个选项,恢复初始选中状态(可根据需求调整) selectedValues = {1}; } else { selectedValues = newSelectedValues; } } }); }, ), ), ); } }
代码关键点说明
- UI层面约束:通过
ButtonSegment的enabled属性动态控制选项可用性,从交互源头避免用户违反规则 - 操作定位:利用集合
difference方法快速定位用户最新操作的选项,解决无法直接获取单个操作项的问题 - 状态强制修正:在
onSelectionChanged中对选中集合进行二次校验,即使UI禁用失效,最终选中状态也符合规则
内容的提问来源于stack exchange,提问作者KiriLL Sabko
相关产品推荐
相关产品推荐

