一、实现RadioButton
1、效果图展示
效果如下如所示,所需要实现的功能是,实现两(多)行多个类目的单项选择。
2、XML布局实现
Android中提供了RadioButton供我们实现多个类目的单项选择,因为一般实现单项选择都需要多个类目中选择其中的一个,故而RadioButton一般需要搭配RadioGroup使用。然而RadioGroup是继承的LinearLayout,所以RadioButton排列方向只有水平或垂直中的一种,但是往往由于我们所添加的类目比较多,一行或一列不够地方陈列,所以有时候我们需要分成两(多)行显示,这个时候单单一个RadioGroup就不适用了,为了实现两(多)行显示,我们就需要用到两(多)组RadioGroup进行搭配。下面是步骤1中效果展示图的xml代码。
<RadioGroup
android:id="@+id/rgp_part_one"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center">
<RadioButton
android:id="@+id/rbt_happy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:textSize="18sp"
android:text="高兴" />
<RadioButton
android:id="@+id/rbt_mad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:textSize="18sp"
android:text="生气" />
<RadioButton
android:id="@+id/rbt_sadness"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:textSize="18sp"
android:text="悲伤" />
</RadioGroup>
<RadioGroup
android:id="@+id/rgp_part_two"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="top|center_horizontal">
<RadioButton
android:id="@+id/rbt_neutral"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:textSize="18sp"
android:text="厌恶" />
<RadioButton
android:id="@+id/rbt_fear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:textSize="18sp"
android:text="恐惧" />
<RadioButton
android:id="@+id/rbt_amazed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:textSize="18sp"
android:text="惊奇" />
</RadioGroup>
3、Java代码监听并执行事件
在步骤2中,我们用的是两(多)组的RadioGroup来实现两(多)行显示,分别表示为rgp_part_one和rgp_part_two,为了达到我们多类目的单项选择的目的,我们需要保证这两(多)组RadioGroup中有且只能有其中一组被选中,即这两(多)组RadioGroup的关系是互斥关系,其中一个被选中之后,剩余的都要清除掉被选中的状态。在MainActivity中,实现onCheckedChanged(RadioGroup group, int checkedId)方法,通过group.getId()来获取当前选中的RadioGroup的ID,并利用check(-1)的方法来清除其余RadioGroup的选中状态。最后通过checkedId来获取具体选中的RadioButton,并执行相对应的事件,代码如下所示。
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (group.getId()){
case R.id.rgp_part_one:
rgp_part_two.check(-1);
System.out.println("*********:rgp_part_two.clearCheck()");
break;
case R.id.rgp_part_two:
rgp_part_one.check(-1);
System.out.println("*********:rgp_part_one.clearCheck()");
break;
}
switch (checkedId){
case R.id.rbt_happy:
emotion_selected=emotions[0];
break;
case R.id.rbt_mad:
emotion_selected=emotions[1];
break;
case R.id.rbt_sadness:
emotion_selected=emotions[2];
break;
case R.id.rbt_neutral:
emotion_selected=emotions[3];
break;
case R.id.rbt_fear:
emotion_selected=emotions[4];
break;
case R.id.rbt_amazed:
emotion_selected=emotions[5];
break;
}
}
二、StackOverflowError报错解决方法
1、StackOverflowError报错原因分析
通过一中的1、2、3,总共三个步骤,实现RadioButton的多类目单项选择,但是按照上述的代码走,到最后面执行的时候,发现了一个问题,即题目中说到的java.lang.StackOverflowError: stack size 8MB onCheckedChanged,刚开始是很蒙蔽的,不知道是什么情况,理论上说,这一套流程走下来应该是没有问题的才对,后来上网查询了相关的资料,应该是循环调用onCheckedChanged()方法所导致,为什么会这样子呢?原因就在check(-1)方法上,下面以rgp_part_two.check(-1)为例。
1)、我们选中rgp_part_one中标签为生气的RadioButton;
2)、这时候会触动onCheckedChanged()方法;
3)、并执行rgp_part_two.check(-1),该方法会遍历所有rgp_part_two组中的RadioButton,并清除该组中的RadioButton的选中状态;
4)、而在清除这些RadioButton的状态的时候,就又会触发onCheckedChanged(),就会从步骤4)回到步骤1),从而形成循环调用,从导致java.lang.StackOverflowError: stack size 8MB onCheckedChanged。
以上就是出现问题的原因。
2、解决方法
要解决这个问题,我们只需要在onCheckedChanged()中添加如下代码即可。
View viewById = group.findViewById(checkedId);
if (viewById==null||!viewById.isPressed()){
return;
}
这几行的代码起到的作用就是,每次触发onCheckedChanged()的时候,先判断是否有RadioButton被按下,如果没有,就返回。这就避免了我们在已经选择好了RadioButton,并且手已经离开屏幕的情况下,还反复触发rgp_part_two.check(-1)方法,导致循环迭代报错。
下面贴上修改过后的onCheckedChanged()方法代码。
public void onCheckedChanged(RadioGroup group, int checkedId) {
View viewById = group.findViewById(checkedId);
if (viewById==null||!viewById.isPressed()){
return;
}
switch (group.getId()){
case R.id.rgp_part_one:
rgp_part_two.check(-1);
System.out.println("*********:rgp_part_two.clearCheck()");
break;
case R.id.rgp_part_two:
rgp_part_one.check(-1);
System.out.println("*********:rgp_part_one.clearCheck()");
break;
}
switch (checkedId){
case R.id.rbt_happy:
emotion_selected=emotions[0];
break;
case R.id.rbt_mad:
emotion_selected=emotions[1];
break;
case R.id.rbt_sadness:
emotion_selected=emotions[2];
break;
case R.id.rbt_neutral:
emotion_selected=emotions[3];
break;
case R.id.rbt_fear:
emotion_selected=emotions[4];
break;
case R.id.rbt_amazed:
emotion_selected=emotions[5];
break;
}
}
以上就是全部代码,可能写的不是很好,有错误的地方,欢迎各位同僚留言批评斧正,谢谢~