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

Flutter实现单选ElevatedButton(附ToggleButtons替代方案)

Flutter 实现单选ElevatedButton组(点击切换选中状态)

要实现多个ElevatedButton的单选功能,核心是把选中状态统一放在父组件管理,子组件只负责根据父组件传递的状态渲染样式,并在点击时通知父组件更新选中状态。以下是具体修改方案:

1. 重构子组件 RecordingSlotButton

把原来带状态的子组件改成无状态组件,通过外部传入选中状态和点击回调,不再自己维护状态:

import 'package:flutter/material.dart';

class RecordingSlotButton extends StatelessWidget {
  final bool isSelected;
  final VoidCallback onPressed;

  const RecordingSlotButton({
    super.key,
    required this.isSelected,
    required this.onPressed,
  });

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      style: ElevatedButton.styleFrom(
        backgroundColor: isSelected ? Colors.blue : Colors.red,
      ),
      onPressed: onPressed,
      child: const Text(""),
    );
  }
}

2. 修改父组件 RecordingSlotContainer

将父组件改为StatefulWidget,维护当前选中的按钮索引,生成按钮时传递对应状态,点击时更新选中索引实现单选:

import 'package:flutter/material.dart';
import 'package:netvideo/widget/recordingslot-button.dart';

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

  @override
  State<RecordingSlotContainer> createState() => _RecordingSlotContainerState();
}

class _RecordingSlotContainerState extends State<RecordingSlotContainer> {
  final int recordingSlots = 5;
  // 维护当前选中的按钮索引,初始为null表示未选中任何按钮
  int? _selectedIndex;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: Column(
            children: List.generate(recordingSlots, (index) {
              return RecordingSlotButton(
                isSelected: _selectedIndex == index,
                onPressed: () {
                  setState(() {
                    // 点击时更新选中索引,实现单选
                    _selectedIndex = index;
                    print("选中第${index+1}个按钮");
                  });
                },
              );
            }),
          ),
        ),
      ),
    );
  }
}

扩展:支持取消选中

如果需要点击已选中的按钮时取消选中状态,只需修改父组件的点击逻辑:

onPressed: () {
  setState(() {
    _selectedIndex = _selectedIndex == index ? null : index;
  });
},

方案说明

  • 父组件通过_selectedIndex统一管理选中状态,所有子按钮的选中状态都由这个值决定
  • 点击任意按钮时,父组件更新_selectedIndex为当前按钮的索引,其他按钮的isSelected会自动变为false,实现单选效果
  • 子组件完全受控于父组件的状态,符合Flutter的状态提升原则,避免了组件间状态不同步的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 22:55:18