前言
平时很多项目中都会用到RadioButton搭配RadioGroup来实现单选,但是有时候在UI上会经常出现多排的情况,这种情况使用RadioGroup搭配RadioButton是无法实现单选情况
为什么RadioGroup搭配RadioButton是无法实现单选
主要是RadioGroup造成
public class RadioGroup extends LinearLayout
RadioGroup 继承 LinearLayout 所有保留了LinearLayout的特性
初始化时候通过监听的方式来添加对RadioButton的监听
private void init() {
mChildOnCheckedChangeListener = new CheckedStateTracker();
mPassThroughListener = new PassThroughHierarchyChangeListener();
super.setOnHierarchyChangeListener(mPassThroughListener);
}
这里就是就是原因,如果RadioGroup包裹的不是RadioButton将不会添加监听
public void onChildViewAdded(View parent, View child) {
if (parent == RadioGroup.this && child instanceof RadioButton) {
int id = child.getId();
// generates an id if it's missing
if (id == View.NO_ID) {
id = View.generateViewId();
child.setId(id);
}
((RadioButton) child).setOnCheckedChangeWidgetListener(
mChildOnCheckedChangeListener);
}
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewAdded(parent, child);
}
}
解决方式
1.采用其他方案
如 使用RecyclerView,自定义控件等,这里只简单提一下
2.自定义RadioGroup
通过重写的RadioGruop的方式来实现对RadioButton 的重新包裹,可以参考源码,不用继承LinearLayout,这样其子控件就可以随意乱摆了
3.包裹RadioGroup
代码如下
lass RadioGroupGroup : LinearLayoutCompat, RadioGroup.OnCheckedChangeListener{
private var mOnCheckedChangeListener: OnCheckedChangeListener? = null
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
private val radioButtonMap = mutableMapOf<Int, RadioButton>()
private val radioGroupMap = mutableMapOf<Int, RadioGroup>()
override fun addView(child: View?, params: ViewGroup.LayoutParams?) {
super.addView(child, params)
if (child is RadioGroup) {
child.setOnCheckedChangeListener(this)
child.forEach {
if (it is RadioButton) {
radioButtonMap[it.id] = it
radioGroupMap[it.id] = child
}
}
}
}
interface OnCheckedChangeListener {
/**
*
* Called when the checked radio button has changed. When the
* selection is cleared, checkedId is -1.
*
* @param group the group in which the checked radio button has changed
* @param checkedId the unique identifier of the newly checked radio button
*/
fun onCheckedChanged(group: RadioGroup?, @IdRes checkedId: Int)
}
//记录最后一次点击的RadioGroup
private var lastRadioGroup: RadioGroup? = null
override fun onCheckedChanged(group: RadioGroup?, checkedId: Int) {
if (group == null || checkedId == -1) {
return
}
if (radioButtonMap[checkedId]?.isChecked == true) {
mOnCheckedChangeListener?.onCheckedChanged(group, checkedId)
if (lastRadioGroup != group && lastRadioGroup!=null){
lastRadioGroup!!.clearCheck()
}
lastRadioGroup = group
}
}
fun check(@IdRes id: Int) {
radioGroupMap[id]?.check(id)
}
fun setOnCheckedChangeListener(listener: OnCheckedChangeListener) {
mOnCheckedChangeListener = listener
}
当然这样会让布局的层次加重,不过代码简单