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

如何实现Flutter ListView中仅单个OutlinedButton可选中?

解决方案:实现单选的分类按钮列表

问题出在每个CreateCategoryButton独立维护自己的选中状态,导致无法互斥选中。我们需要把选中状态统一放到父组件管理,让子组件根据父组件传递的状态来渲染,点击时通知父组件更新选中项。

修改步骤:

  1. 父组件维护选中状态
    在_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;
              });
            },
          ),
        );
      },
    );
  }
}
  1. 子组件依赖父组件传递的状态
    移除_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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 07:07:23