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

Flutter按钮单选颜色切换异常:点击单个按钮却同时变色

解决Flutter单选按钮组的互斥选中问题

嘿,我看你现在遇到了单选按钮的状态互斥问题——两个按钮各自维护自己的isButtonPressed变量,导致点击时它们的状态完全独立,自然会出现同时变绿的情况。咱们来一步步修复这个问题:

问题根源

你给每个按钮都单独定义了bool isButtonPressed变量,这两个变量之间没有任何关联:点击第一个按钮只会切换它自己的状态,第二个按钮的状态不会受到影响;同理点击第二个按钮也只会改变它自己的状态。所以就会出现两个按钮同时处于“选中(绿色)”状态的异常。

解决方案:用单一状态变量管理选中状态

我们可以用一个统一的变量来记录哪个按钮被选中,这样就能实现互斥的单选效果。比如用一个整数(或者枚举类型):

  • null 代表没有按钮被选中
  • 1 代表第一个按钮(Startup Pack)被选中
  • 2 代表第二个按钮(Stunning Solo)被选中

修改后的完整代码示例

首先在你的State类中定义这个状态变量:

// 放在State类的顶部,和其他成员变量一起
int? selectedButton;

然后修改第一个按钮的代码:

Widget startupButton() { 
  return ClipRRect( 
    borderRadius: BorderRadius.circular(15.0), 
    child: SizedBox( 
      height: 150, 
      width: MediaQuery.of(context).size.width * 0.45, 
      child: RaisedButton( 
        // 根据统一的选中状态判断按钮颜色
        color: selectedButton == 1 ? Colors.green : Colors.red, 
        onPressed: () { 
          setState(() { 
            // 点击时选中第一个按钮,自动取消第二个的选中状态
            selectedButton = 1; 
            // 如果需要支持取消选中,可以改成下面这行:
            // selectedButton = selectedButton == 1 ? null : 1;
          }); 
        }, 
        child: Column( 
          children: [ 
            Padding( 
              padding: const EdgeInsets.only(top: 20.0), 
              child: Text('Startup Pack', style: TextStyle(fontSize: 15, color: Colors.black)), 
            ), 
            Text('Introductory Offer', style: TextStyle(fontSize: 12, color: Colors.black)), 
            Padding( 
              padding: const EdgeInsets.all(10.0), 
              child: Row( 
                mainAxisAlignment: MainAxisAlignment.center, 
                mainAxisSize: MainAxisSize.max, 
                crossAxisAlignment: CrossAxisAlignment.center, 
                children: <Widget>[ 
                  Text( 
                    "\$$dollars", 
                    style: TextStyle( 
                      fontWeight: FontWeight.bold, 
                      fontSize: 20, 
                      decoration: TextDecoration.lineThrough), 
                  ), 
                  SizedBox(width: 5), 
                  Text( 
                    "\$$dollars2", 
                    style: TextStyle( 
                      fontWeight: FontWeight.bold, 
                      fontSize: 20, 
                      color: primaryColor), 
                  ), 
                ]), 
            ), 
            Text( 
              "Per year", 
              style: TextStyle( 
                fontWeight: FontWeight.bold, 
                fontSize: 13, 
                color: blackColor), 
            ), 
            Text( 
              "Billed anually", 
              style: TextStyle( 
                fontWeight: FontWeight.bold, 
                fontSize: 13, 
                color: blackColor), 
            ), 
          ], 
        ), 
      ), 
    ), 
  ); 
} 

接着修改第二个按钮的代码:

Widget freeButton() { 
  return ClipRRect( 
    borderRadius: BorderRadius.circular(15.0), 
    child: SizedBox( 
      height: 150, 
      width: MediaQuery.of(context).size.width * 0.45, 
      child: RaisedButton( 
        // 根据统一的选中状态判断按钮颜色
        color: selectedButton == 2 ? Colors.green : Colors.red, 
        onPressed: () { 
          setState(() { 
            // 点击时选中第二个按钮,自动取消第一个的选中状态
            selectedButton = 2; 
            // 如果需要支持取消选中,可以改成下面这行:
            // selectedButton = selectedButton == 2 ? null : 2;
          }); 
        }, 
        child: Column( 
          children: [ 
            Padding( 
              padding: const EdgeInsets.only(top: 20.0), 
              child: Text('Stunning Solo', style: TextStyle(fontSize: 15,color: Colors.black)), 
            ), 
            Text('Free Forever', style: TextStyle(fontSize: 12,color: Colors.black)), 
            Padding( 
              padding: const EdgeInsets.all(10.0), 
              child: Row( 
                mainAxisAlignment: MainAxisAlignment.center, 
                mainAxisSize: MainAxisSize.max, 
                crossAxisAlignment: CrossAxisAlignment.center, 
                children: <Widget>[ 
                  Text( 
                    "\$$dollars3", 
                    style: TextStyle( 
                      fontWeight: FontWeight.bold, 
                      fontSize: 20, 
                      color: blackColor), 
                  ), 
                  SizedBox(width: 5), 
                ]), 
            ), 
            Text( 
              "Free forever", 
              style: TextStyle( 
                fontWeight: FontWeight.bold, 
                fontSize: 13, 
                color: blackColor), 
            ), 
          ], 
        ), 
      ), 
    ), 
  ); 
}

效果说明

现在点击第一个按钮时,selectedButton会被设为1,第一个按钮变成绿色,第二个按钮因为selectedButton != 2会自动恢复红色;点击第二个按钮时同理,selectedButton设为2,第二个变绿,第一个变回红色,完美实现你想要的单选交互效果。

如果需要支持“取消选中”的功能,只需要把按钮onPressed里的代码替换成注释里的那行就行——点击已选中的按钮时,会把selectedButton设为null,两个按钮都恢复默认的红色。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 08:07:57