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

Flutter中如何实现ListView.builder生成的按钮仅被点击的那个变色

问题根因

你当前所有按钮共用同一个全局pressAttention状态变量,只要状态更新所有按钮的颜色判断逻辑都会同步生效,自然会出现全选/全不选的联动效果。根据你的使用场景可以选择以下两种解决方案:


方案1:单选模式(仅允许同时选中一个按钮)

用可空整型记录当前选中的按钮索引即可,修改代码如下:

List<String> litems = ["Counter No 1", "Counter No 2", "Counter No 3", "Counter No 4"];
// 替换原来的bool变量,记录当前选中的索引,初始为null表示没有选中项
int? selectedIndex;

Widget build(BuildContext context) {
  return SafeArea(
    child: SingleChildScrollView(
      child: SizedBox(
        height: MediaQuery.of(context).size.height,
        child: ListView.builder(
          shrinkWrap: true,
          itemCount: litems.length,
          itemBuilder: (BuildContext ctxt, int index) {
            return Column(
              children: [
                Container(
                  height: 55.0,
                  width: MediaQuery.of(context).size.width*0.9,
                  child: RaisedButton(
                    child: Text(litems[index]),
                    textColor: Colors.white,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(30.0),
                    ),
                    // 判断当前索引是否是选中的索引,决定颜色
                    color: selectedIndex == index ? Colors.green : Colors.grey,
                    onPressed: () => setState(() {
                      // 点击已选中的按钮可以取消选中,不需要的话直接赋值selectedIndex = index即可
                      selectedIndex = selectedIndex == index ? null : index;
                    }), 
                  ),
                ),
                SizedBox(height: 20),
              ],
            );
          }),
      ),
    ),
  );
}

方案2:多选模式(允许同时选中多个按钮)

用布尔数组记录每一个按钮的选中状态:

List<String> litems = ["Counter No 1", "Counter No 2", "Counter No 3", "Counter No 4"];
// 存储每个位置按钮的选中状态
late List<bool> pressStatus;

// 初始化状态数组,要写在State类的initState方法里
@override
void initState() {
  super.initState();
  pressStatus = List.generate(litems.length, (index) => false);
}

Widget build(BuildContext context) {
  return SafeArea(
    child: SingleChildScrollView(
      child: SizedBox(
        height: MediaQuery.of(context).size.height,
        child: ListView.builder(
          shrinkWrap: true,
          itemCount: litems.length,
          itemBuilder: (BuildContext ctxt, int index) {
            return Column(
              children: [
                Container(
                  height: 55.0,
                  width: MediaQuery.of(context).size.width*0.9,
                  child: RaisedButton(
                    child: Text(litems[index]),
                    textColor: Colors.white,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(30.0),
                    ),
                    // 取当前索引对应的状态判断颜色
                    color: pressStatus[index] ? Colors.green : Colors.grey,
                    onPressed: () => setState(() {
                      // 仅修改当前索引对应的状态
                      pressStatus[index] = !pressStatus[index];
                    }), 
                  ),
                ),
                SizedBox(height: 20),
              ],
            );
          }),
      ),
    ),
  );
}

小提示:RaisedButton已在Flutter 2.0+版本废弃,建议替换为ElevatedButton使用,参数逻辑基本一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 03:24:06