如何实现Flutter ListView中仅单个OutlinedButton可选中?
解决方案:实现单选的分类按钮列表
问题出在每个CreateCategoryButton独立维护自己的选中状态,导致无法互斥选中。我们需要把选中状态统一放到父组件管理,让子组件根据父组件传递的状态来渲染,点击时通知父组件更新选中项。
修改步骤:
- 父组件维护选中状态
在_CategoriesListViewState中添加_selectedIndex变量,用来记录当前选中的按钮索引:
class _CategoriesListViewState extends State<CategoriesListView> { // 初始值设为-1,表示未选中任何按钮 int _selectedIndex = -1; @override Widget build(BuildContext context) { return ListView.builder( shrinkWrap: true, scrollDirection: Axis.horizontal, itemCount: widget.categories.length, itemBuilder: (BuildContext context, int index) { return Padding( padding: const EdgeInsets.all(8.0), child: CreateCategoryButton( category: widget.categories[index], index: index, // 传递当前按钮是否选中的状态 isSelected: _selectedIndex == index, // 点击时更新选中索引 onPressed: () { setState(() { _selectedIndex = index; }); }, ), ); }, ); } }
- 子组件依赖父组件传递的状态
移除_CreateCategoryButtonState中的isSelected变量,改为接收父组件传递的参数,并根据该参数渲染样式:
// 先修改CreateCategoryButton的外部类,添加isSelected参数 class CreateCategoryButton extends StatefulWidget { final String category; final int index; final bool isSelected; // 新增参数 final VoidCallback onPressed; const CreateCategoryButton({ super.key, required this.category, required this.index, required this.isSelected, required this.onPressed, }); @override State<CreateCategoryButton> createState() => _CreateCategoryButtonState(); } class _CreateCategoryButtonState extends State<CreateCategoryButton> { // 移除自己维护的isSelected变量 @override Widget build(BuildContext context) { return OutlinedButton( style: OutlinedButton.styleFrom( // 使用父组件传递的isSelected状态 backgroundColor: widget.isSelected ? Constants.backGroudColor : Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), side: const BorderSide( color: Colors.black, width: 0.7, ), ), onPressed: () { widget.onPressed(); // 调用父组件的回调 }, child: Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Text( widget.category, style: TextStyle( color: Constants.textAndButtomColor, fontSize: 16, fontFamily: GoogleFonts.montserratAlternates().fontFamily), ), ), ); } }
说明:
- 父组件通过
_selectedIndex统一控制当前选中的按钮,每次点击按钮时更新该值,触发父组件重绘。 - 每个子组件根据父组件传递的
isSelected参数判断自己是否选中,从而应用对应的样式。 - 这样就能保证同一时间只有一个按钮处于选中状态,满足筛选的单选需求。
内容的提问来源于stack exchange,提问作者tehphilb
相关产品推荐
相关产品推荐

