RadioGroup和RadioButton解析,以及它们的监听器
来源:互联网 发布:淘宝劳保用品 编辑:程序博客网 时间:2024/06/07 02:36
RadioButton继承于CompoundButton,它与CheckBox的区别是不能通过点击自己在选中与未选中状态之间切换,但是CheckBox可以。
RadioGroup是放置RadioButton的容器,同一时刻在同一个RadioGroup中的一组RadioButton中只有一个处于checked状态。
RadioButton的父类CompoundButton定义了一个OnCheckedChangeListener监听器,针对这个监听器有两个成员:mOnCheckedChangeListener和mOnCheckedChangeWidgetListener【供内部使用的】
看下RadioButton的setChecked(boolean checked)方法:
public void setChecked(boolean checked) { if (mChecked != checked) { mChecked = checked; refreshDrawableState(); notifyViewAccessibilityStateChangedIfNeeded( AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); // Avoid infinite recursions if setChecked() is called from a listener if (mBroadcasting) { return; } mBroadcasting = true; if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener.onCheckedChanged(this, mChecked); } if (mOnCheckedChangeWidgetListener != null) { mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked); } mBroadcasting = false; } }
主要的操作是:
1.调用refreshDrawableState()
改变RadioButton的背景图片;
2.若mOnCheckedChangeListener!=null
则调用mOnCheckedChangeListener.onCheckedChanged(this, mChecked)
,同时如果mOnCheckedChangeWidgetListener!=null
,调用mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked)
RadioGroup内部定义了一个OnCheckedChangeListener监听器,主要是处理RadioButton切换的监听响应。
在RadioGroup的构造方法中调用了init()
方法:
private void init() { mChildOnCheckedChangeListener = new CheckedStateTracker(); mPassThroughListener = new PassThroughHierarchyChangeListener(); super.setOnHierarchyChangeListener(mPassThroughListener); }
在init()
内部设置了super.setOnHierarchyChangeListener(mPassThroughListener)
。
其中mPassThroughListener是一个自定义的继承于ViewGroup.OnHierarchyChangeListener的监听器。
在该监听器的onChildViewAdded(View parent, View child)
方法中调用了((RadioButton) child).setOnCheckedChangeWidgetListener( mChildOnCheckedChangeListener)
即为当前添加的RadioButton控件设置了mOnCheckedChangeWidgetListener。
mChildOnCheckedChangeListener是CheckedStateTracker类的实例,也是在init()中初始化的。
CheckedStateTracker继承于CompoundButton.OnCheckedChangeListener,该类的onCheckedChanged(CompoundButton buttonView, boolean isChecked)方法内部主要是执行了以下步骤:
1.调用setCheckedStateForView(mCheckedId, false)
:
private void setCheckedStateForView(int viewId, boolean checked) { View checkedView = findViewById(viewId); if (checkedView != null && checkedView instanceof RadioButton) { ((RadioButton) checkedView).setChecked(checked); } }
将之前选中的radiobutton的id:mCheckedId对应设置为未选中【这里有个地方需要注意的是:在这之前需要将变量mProtectFromCheckedChange
设置为了true,因为在((RadioButton) checkedView).setChecked(false);
之后必然会调用RadioButton的onCheckedChanged()(在RadioGroup的构造方法中就为添加的RadioButton设置的监听器),引起死循环的递归调用】
2.调用setCheckedId()
:
private void setCheckedId(@IdRes int id) { mCheckedId = id; if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId); } }
将当前buttonView对应的id通过调用setCheckedId(id)
设置为选中状态,此时如果RadioGroup的mOnCheckedChangeListener不为null则调用mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId)
执行状态监听器的监听方法。
现在看下RadioGroup的check(int id)方法:
public void check(@IdRes int id) { // don't even bother if (id != -1 && (id == mCheckedId)) { return; } if (mCheckedId != -1) { setCheckedStateForView(mCheckedId, false); } if (id != -1) { setCheckedStateForView(id, true); } setCheckedId(id); }
1.如果当前选中的RadioButton的id与mCheckedId相等则直接返回;
2.mCheckedId 不等于-1则说明之前有选中的RadioButton则调用setCheckedStateForView(mCheckedId, false)
将其变为unchecked状态。【因为RadioButton的状态改变了,所以会调用RadioButton的onCheckedChanged(CompoundButton buttonView, boolean isChecked)方法(在RadioGroup的构造方法中我RadioButton设置的监听器),即CheckedStateTracker中的onCheckedChanged(CompoundButton buttonView, boolean isChecked)方法】
3.如果id不等于-1则说明是有效id,则调用setCheckedStateForView(mCheckedId, false)
将其变为checked状态。【因为RadioButton的状态改变了,所以会调用RadioButton的onCheckedChanged(CompoundButton buttonView, boolean isChecked)方法(在RadioGroup的构造方法中我RadioButton设置的监听器),即CheckedStateTracker中的onCheckedChanged(CompoundButton buttonView, boolean isChecked)方法】
4.调用setCheckedId(id)
方法将mCheckedId 赋值为id,同时如果RadioGroup的mOnCheckedChangeListener != null
则调用起mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId)
方法
综上分析,RadioGroup类其实已经为添加在其中的每一个RadioButton的成员变量mOnCheckedChangeWidgetListener赋值了,即为RadioButton设置了内部使用的OnCheckedChangeListener。
通过代码往RadioGroup中添加RadioButton的时候,如果写成:
mRgProductCategories.setOnCheckedChangeListener(this);//默认选中index位置的产品种类 mRgProductCategories.check(mRgProductCategories.getChildAt(index).getId());
会导致RadioGroup的onCheckedChanged()监听方法执行2次【mCheckedId等于-1时是2次,如果之前mCheckedId不等于-1会是3次】,改为下面这样就可以避免上面的情况发生:
mRgProductCategories.setOnCheckedChangeListener(this); //默认选中index位置的产品种类 ((RadioButton)mRgProductCategories.getChildAt(index)).setChecked(true);
还有一个问题是如果:
mRgProductCategories.setOnCheckedChangeListener(this);mRgProductCategories.clearCheck();
先设置监听器在清楚所有点击态,会导致在setCheckedStateForView(mCheckedId, false);
之后调用一次RadioGroup的onCheckChanged(RadioGroup group, int checkedId)方法。
如果不想调用把上面两个方法交换一下位置即可:
mRgProductCategories.clearCheck();mRgProductCategories.setOnCheckedChangeListener(this);
- RadioGroup和RadioButton解析,以及它们的监听器
- CheckBox和RadioButton以及RadioGroup
- RadioButton和CheckBox的区别,RadioButton&RadioGroup
- RadioGroup和RadioButton的实现
- RadioButton和RadioGroup的使用
- RadioGroup以及RadioButton自定义样式的使用
- android RadioGroup和RadioButton的用法
- 控件RadioGroup、RadioButton和CheckBox的使用
- Android—RadioGroup和RadioButton的使用
- 兔子-RadioButton和RadioGroup的关系
- RadioGroup和RadioButton的简单使用
- 可以解决RadioGroup中两个RadioButton选中以及RadioButton回行布局的RadioGroup
- RadioGroup 和RadioButton制作Tab修改RadioButton的大小
- RadioGroup和RadioButton
- RadioGroup和RadioButton
- RadioGroup和RadioButton
- RadioGroup和RadioButton
- 使用RadioButton 和RadioGroup
- [by 王谭]oracle游标的使用教程
- 数据库-内连接&外连接
- 扫我服务器的目录
- 来啊抢劫啊198. House Robber
- 7、(七)外汇基础篇之外币拆借交易
- RadioGroup和RadioButton解析,以及它们的监听器
- NSUrlConnection 网络下载
- String字符串工具类
- [LeetCode] Regular Expression Matching
- bootstrap菜单代码
- js字符串转json, json转字符串
- IntelliJ IDEA(2017)
- Protobuf 的 proto3 与 proto2 的区别
- css定位