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

Flutter实现单选按钮组:修复多选及无法取消选中问题

Flutter 实现单选尺寸按钮组(一行五个)

问题根源分析

原代码的核心问题在于状态管理逻辑错误:

  • 把选中状态存在StatefulWidget的成员变量中,违反了Flutter中Widget不可变的设计原则
  • 每个SizeButton独立维护自身状态,多个按钮之间无法共享状态,导致单选逻辑失效
  • 点击时仅修改自身对应的状态变量,无法同步重置其他按钮的选中状态

解决方案:状态提升 + 无状态子组件

将单选组的选中状态统一交给父组件管理,子组件仅负责根据传入的状态渲染样式,并触发点击回调。这样就能保证同一时间只有一个按钮被选中。

重构后的子组件(SizeOptionButton)

改为无状态组件,仅负责渲染和触发回调,状态由父组件传入:

import 'package:flutter/material.dart';

class SizeOptionButton extends StatelessWidget {
  final String text;
  final bool isSelected;
  final VoidCallback onTap;

  const SizeOptionButton({
    super.key,
    required this.text,
    required this.isSelected,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      child: Container(
        width: 40,
        height: 40,
        decoration: BoxDecoration(
          border: Border.all(color: Colors.grey, width: 1),
          shape: BoxShape.circle,
          color: isSelected ? Colors.red : Colors.white,
        ),
        child: Center(
          child: Text(
            text,
            style: TextStyle(
              fontSize: 20,
              color: isSelected ? Colors.white : Colors.black,
            ),
          ),
        ),
      ),
    );
  }
}

父组件使用示例

在父组件中维护当前选中的尺寸,点击按钮时更新状态,同步所有按钮的选中状态:

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

  @override
  State<SizeSelector> createState() => _SizeSelectorState();
}

class _SizeSelectorState extends State<SizeSelector> {
  // 维护当前选中的尺寸,null表示未选中
  String? _selectedSize;

  // 定义所有尺寸选项
  final List<String> _sizes = ['XS', 'S', 'M', 'L', 'XL'];

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: _sizes.map((size) {
        return SizeOptionButton(
          text: size,
          isSelected: _selectedSize == size,
          onTap: () {
            setState(() {
              // 点击已选中的按钮可取消选中(不需要取消则改为`_selectedSize = size`)
              _selectedSize = _selectedSize == size ? null : size;
            });
          },
        );
      }).toList(),
    );
  }
}

关键优化点

  • 状态统一管理:父组件维护_selectedSize,所有按钮根据这个值判断是否选中,确保单选逻辑绝对正确
  • 子组件职责单一:仅负责渲染和触发回调,无内部状态,复用性和可维护性更强
  • 灵活控制取消选中:可通过修改点击逻辑,决定是否允许取消已选中的按钮

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 21:55:25