Flutter实现单选ElevatedButton(附ToggleButtons替代方案)
要实现多个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
相关产品推荐
相关产品推荐

