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
相关产品推荐
相关产品推荐

