Skip to content

Selection

Flutter 提供多种选择控件:Checkbox(复选框)、Radio(单选框)、Switch(开关)、Slider(滑块)。

构造函数

Checkbox

dart
Checkbox({
  Key? key,                                                        // 组件标识
  required bool? value,                                            // 选中状态(必填,null 为三态)
  bool tristate = false,                                          // 是否启用三态(false → true → null)
  required ValueChanged<bool?>? onChanged,                         // 状态变化回调(必填)
  MouseCursor? mouseCursor,                                       // 鼠标指针
  Color? activeColor,                                            // 选中颜色
  Color? fillColor,                                               // 填充颜色
  Color? checkColor,                                              // 勾选标记颜色
  Color? focusColor,                                             // 焦点颜色
  Color? hoverColor,                                             // 悬停颜色
  Color? overlayColor,                                            // 覆盖颜色
  double splashRadius,                                            // 水波纹半径
  MaterialTapTargetSize? materialTapTargetSize,                   // 触摸目标大小
  VisualDensity? visualDensity,                                  // 视觉密度
  FocusNode? focusNode,                                          // 焦点节点
  bool autofocus = false,                                         // 自动焦点
  OutlinedBorder? shape,                                         // 形状
  BorderSide? side,                                              // 边框
})

CheckboxListTile

dart
CheckboxListTile({                                                 // 带标题和副标题的复选框
  Key? key,
  required bool? value,                                            // 选中状态
  required ValueChanged<bool?>? onChanged,                         // 变化回调
  Color? activeColor,                                            // 选中颜色
  Widget? title,                                                  // 标题
  Widget? subtitle,                                               // 副标题
  bool isThreeLine = false,                                      // 是否三行高度
  bool dense = false,                                            // 是否紧凑
  bool secondary,                                                // 右侧控件
  bool selected = false,                                         // 是否选中(影响文字颜色)
  ListTileControlAffinity controlAffinity = ListTileControlAffinity.platform, // 控件位置
  bool autofocus = false,
  EdgeInsetsGeometry? contentPadding,                            // 内边距
})

Radio

dart
Radio<T>({
  Key? key,
  required T value,                                                // 当前选项值(必填)
  required T? groupValue,                                         // 当前选中值(必填)
  required ValueChanged<T?>? onChanged,                           // 变化回调(必填)
  Color? activeColor,                                            // 选中颜色
  Color? fillColor,                                              // 填充颜色
  Color? focusColor,                                             // 焦点颜色
  Color? hoverColor,                                             // 悬停颜色
  Color? overlayColor,                                            // 覆盖颜色
  double splashRadius,                                            // 水波纹半径
  MaterialTapTargetSize? materialTapTargetSize,
  VisualDensity? visualDensity,
  FocusNode? focusNode,
  bool autofocus = false,
  MouseCursor? mouseCursor,
  bool toggleable = false,                                       // 是否可取消选中
})

RadioListTile

dart
RadioListTile<T>({                                                 // 带标题的单选项
  Key? key,
  required T value,
  required T? groupValue,
  required ValueChanged<T?>? onChanged,
  Color? activeColor,
  Widget? title,
  Widget? subtitle,
  bool isThreeLine = false,
  bool dense = false,
  Widget? secondary,
  bool selected = false,
  ListTileControlAffinity controlAffinity = ListTileControlAffinity.platform,
  bool autofocus = false,
  EdgeInsetsGeometry? contentPadding,
})

Switch

dart
Switch({
  Key? key,
  required bool value,                                            // 开关状态(必填)
  required ValueChanged<bool> onChanged,                           // 变化回调(必填)
  Color? activeColor,                                            // 开启颜色(滑块轨道)
  Color? activeTrackColor,                                       // 开启轨道颜色
  Color? inactiveThumbColor,                                      // 关闭滑块颜色
  Color? inactiveTrackColor,                                     // 关闭轨道颜色
  Color? thumbColor,                                             // 滑块颜色
  Color? trackColor,                                             // 轨道颜色
  ImageProvider? activeThumbImage,                               // 开启滑块图片
  ImageProvider? inactiveThumbImage,                             // 关闭滑块图片
  MaterialTapTargetSize? materialTapTargetSize,
  DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  Color? focusColor,
  Color? hoverColor,
  FocusNode? focusNode,
  bool autofocus = false,
})

SwitchListTile

dart
SwitchListTile({                                                   // 带标题的开关
  Key? key,
  required bool value,
  required ValueChanged<bool> onChanged,
  Color? activeColor,
  Widget? title,
  Widget? subtitle,
  bool isThreeLine = false,
  bool dense = false,
  Widget? secondary,
  bool selected = false,
  ListTileControlAffinity controlAffinity = ListTileControlAffinity.platform,
  bool autofocus = false,
  EdgeInsetsGeometry? contentPadding,
})

Slider

dart
Slider({
  Key? key,
  required double value,                                           // 当前值(必填)
  required double min = 0.0,                                      // 最小值
  required double max = 1.0,                                      // 最大值
  required ValueChanged<double>? onChanged,                        // 值变化回调(必填)
  ValueChanged<double>? onChangeStart,                            // 开始拖动回调
  ValueChanged<double>? onChangeEnd,                              // 结束拖动回调
  int? divisions,                                                 // 离散分段数(null 为连续)
  String? label,                                                  // 拖动时显示的标签
  Color? activeColor,                                            // 激活颜色
  Color? inactiveColor,                                          // 非激活颜色
  Color? thumbColor,                                             // 滑块颜色
  MouseCursor? mouseCursor,
  SemanticFormatterCallback? semanticFormatterCallback,
  FocusNode? focusNode,
  bool autofocus = false,
})

RangeSlider

dart
RangeSlider({                                                      // 范围滑块
  Key? key,
  required RangeValues values,                                     // 当前范围值(必填)
  required double min = 0.0,                                      // 最小值
  required double max = 1.0,                                      // 最大值
  required ValueChanged<RangeValues>? onChanged,                   // 值变化回调(必填)
  ValueChanged<RangeValues>? onChangeStart,
  ValueChanged<RangeValues>? onChangeEnd,
  int? divisions,
  RangeLabels? labels,                                             // 起止标签
  Color? activeColor,
  Color? inactiveColor,
  MouseCursor? mouseCursor,
  SemanticFormatterCallback? semanticFormatterCallback,
  FocusNode? focusNode,
  bool autofocus = false,
})

属性速查

选择控件对比

控件用途状态类型典型场景
Checkbox多选bool?同意条款、多标签选择
Radio单选T (泛型)性别、支付方式
Switch开关bool设置开关、通知开关
Slider范围值double音量、亮度、价格范围

Checkbox 属性速查

属性类型默认值说明
valuebool?必填选中状态,null 为三态
onChangedValueChanged<bool?>?必填状态变化回调
tristateboolfalse三态模式:false → true → null
activeColorColor?主题色选中颜色
checkColorColor?白色勾选标记颜色
fillColorMaterialStateProperty<Color?>?null填充颜色(可按状态)

Radio 属性速查

属性类型默认值说明
valueT必填当前选项的值
groupValueT?必填当前选中的值(同一组共享)
onChangedValueChanged<T?>?必填选中回调
activeColorColor?主题色选中颜色
toggleableboolfalse是否可取消选中

Switch 属性速查

属性类型默认值说明
valuebool必填开关状态
onChangedValueChanged<bool>必填状态变化回调
activeColorColor?主题色开启时轨道颜色
activeTrackColorColor?null开启时轨道颜色
inactiveThumbColorColor?null关闭时滑块颜色
inactiveTrackColorColor?null关闭时轨道颜色

Slider 属性速查

属性类型默认值说明
valuedouble必填当前值
mindouble0.0最小值
maxdouble1.0最大值
onChangedValueChanged<double>?必填值变化回调
divisionsint?null离散分段数,null 为连续
labelString?null拖动时标签
activeColorColor?主题色已滑过部分颜色
inactiveColorColor?灰色未滑过部分颜色

ListTile 控件位置速查

controlAffinity说明
ListTileControlAffinity.leading控件在左侧(默认)
ListTileControlAffinity.trailing控件在右侧
ListTileControlAffinity.platform跟随平台

快速示例

Checkbox

dart
bool isChecked = false;

Checkbox(
  value: isChecked,
  onChanged: (value) {
    setState(() => isChecked = value!);
  },
  activeColor: Colors.blue,
)

// 带 ListTile
CheckboxListTile(
  value: isChecked,
  onChanged: (value) => setState(() => isChecked = value!),
  title: Text('同意用户协议'),
  subtitle: Text('请阅读并同意'),
  controlAffinity: ListTileControlAffinity.leading,     // 复选框在左
)

Radio

dart
enum Gender { male, female }
Gender? selectedGender;

Column(
  children: [
    Radio<Gender>(
      value: Gender.male,
      groupValue: selectedGender,
      onChanged: (value) => setState(() => selectedGender = value),
    ),
    Radio<Gender>(
      value: Gender.female,
      groupValue: selectedGender,
      onChanged: (value) => setState(() => selectedGender = value),
    ),
  ],
)

// 带 ListTile
RadioListTile<Gender>(
  value: Gender.male,
  groupValue: selectedGender,
  onChanged: (value) => setState(() => selectedGender = value),
  title: Text('男'),
)

Switch

dart
bool notificationsEnabled = true;

Switch(
  value: notificationsEnabled,
  onChanged: (value) => setState(() => notificationsEnabled = value),
  activeColor: Colors.green,
)

// 带 ListTile
SwitchListTile(
  value: notificationsEnabled,
  onChanged: (value) => setState(() => notificationsEnabled = value),
  title: Text('推送通知'),
  subtitle: Text('接收新消息通知'),
)

Slider

dart
double volume = 50;

Slider(
  value: volume,
  min: 0,
  max: 100,
  divisions: 10,                    // 离散 10 档
  label: volume.round().toString(),  // 拖动时显示标签
  onChanged: (value) => setState(() => volume = value),
)

// 范围滑块
RangeValues priceRange = RangeValues(100, 500);

RangeSlider(
  values: priceRange,
  min: 0,
  max: 1000,
  divisions: 20,
  labels: RangeLabels(${priceRange.start.round()}', ${priceRange.end.round()}'),
  onChanged: (values) => setState(() => priceRange = values),
)

完整设置页面示例

dart
class SettingsPage extends StatefulWidget {
  @override
  _SettingsPageState createState() => _SettingsPageState();
}

class _SettingsPageState extends State<SettingsPage> {
  bool darkMode = false;
  bool notifications = true;
  double fontSize = 16;
  String language = 'zh';

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        SwitchListTile(
          title: Text('深色模式'),
          value: darkMode,
          onChanged: (v) => setState(() => darkMode = v),
        ),
        SwitchListTile(
          title: Text('通知'),
          subtitle: Text('接收推送通知'),
          value: notifications,
          onChanged: (v) => setState(() => notifications = v),
        ),
        ListTile(
          title: Text('字体大小: ${fontSize.round()}'),
          subtitle: Slider(
            value: fontSize,
            min: 12,
            max: 24,
            divisions: 6,
            label: fontSize.round().toString(),
            onChanged: (v) => setState(() => fontSize = v),
          ),
        ),
        RadioListTile<String>(
          title: Text('中文'),
          value: 'zh',
          groupValue: language,
          onChanged: (v) => setState(() => language = v!),
        ),
        RadioListTile<String>(
          title: Text('English'),
          value: 'en',
          groupValue: language,
          onChanged: (v) => setState(() => language = v!),
        ),
      ],
    );
  }
}

常见错误

1. Radio 的 groupValue 未共享

dart
// ❌ 错误:每个 Radio 用不同的变量
Radio(value: 1, groupValue: selected1, onChanged: ...),
Radio(value: 2, groupValue: selected2, onChanged: ...),  // 不同的变量!

// ✅ 修复:同一组 Radio 共享同一个 groupValue
Radio(value: 1, groupValue: selectedGender, onChanged: ...),
Radio(value: 2, groupValue: selectedGender, onChanged: ...),

2. onChanged 为 null 导致无法交互

dart
// ❌ 错误:条件禁用时直接传 null
Checkbox(
  value: isChecked,
  onChanged: isEnabled ? null : (v) {},   // 逻辑反了!
)

// ✅ 修复:isEnabled 为 true 时传回调,false 时传 null
Checkbox(
  value: isChecked,
  onChanged: isEnabled ? (v) => setState(() => isChecked = v!) : null,
)

基于 Flutter 官方文档整理