自定义RadioGrop,支持添加包裹着的RadioButton

2024-09-02 21:48

本文主要是介绍自定义RadioGrop,支持添加包裹着的RadioButton,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

控件类:

package com.chinaCEB.cebView;import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.LinearLayout;//这个类是源码RadioGroup复制出来,增加了递归查找子控件RadioButton
public class CebReadioGroup extends LinearLayout {// holds the checked id; the selection is empty by defaultprivate int mCheckedId = -1;// tracks children radio buttons checked stateprivate CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;// when true, mOnCheckedChangeListener discards eventsprivate boolean mProtectFromCheckedChange = false;private OnCheckedChangeListener mOnCheckedChangeListener;private PassThroughHierarchyChangeListener mPassThroughListener;/*** {@inheritDoc}*/public CebReadioGroup(Context context) {super(context);init();}/*** {@inheritDoc}*/public CebReadioGroup(Context context, AttributeSet attrs) {super(context, attrs);init();}private void init() {mCheckedId = View.NO_ID;
//      setOrientation(VERTICAL);   //可以在这里设置线性布局方向mChildOnCheckedChangeListener = new CheckedStateTracker();mPassThroughListener = new PassThroughHierarchyChangeListener();super.setOnHierarchyChangeListener(mPassThroughListener);}/*** {@inheritDoc}*/@Overridepublic void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {// the user listener is delegated to our pass-through listenermPassThroughListener.mOnHierarchyChangeListener = listener;}/*** {@inheritDoc}*/@Overrideprotected void onFinishInflate() {super.onFinishInflate();// checks the appropriate radio button as requested in the XML fileif (mCheckedId != View.NO_ID) {mProtectFromCheckedChange = true;setCheckedStateForView(mCheckedId, true);mProtectFromCheckedChange = false;setCheckedId(mCheckedId);}}/** 递归查找具有选中属性的子控件 */private static CompoundButton findCheckedView(View child) {if (child instanceof CompoundButton)return (CompoundButton) child;if (child instanceof ViewGroup) {ViewGroup group = (ViewGroup) child;for (int i = 0, j = group.getChildCount(); i < j; i++) {CompoundButton check = findCheckedView(group.getChildAt(i));if (check != null)return check;}}return null;// 没有找到}@Overridepublic void addView(View child, int index, ViewGroup.LayoutParams params) {final CompoundButton view = findCheckedView(child);if (view != null) {if (view.isChecked()) {mProtectFromCheckedChange = true;if (mCheckedId != -1) {setCheckedStateForView(mCheckedId, false);}mProtectFromCheckedChange = false;setCheckedId(view.getId());}}super.addView(child, index, params);}/*** <p>* Sets the selection to the radio button whose identifier is passed in* parameter. Using -1 as the selection identifier clears the selection;* such an operation is equivalent to invoking {@link #clearCheck()}.* </p>* * @param id*            the unique id of the radio button to select in this group* * @see #getCheckedRadioButtonId()* @see #clearCheck()*/public void check(int id) {// don't even botherif (id != -1 && (id == mCheckedId)) {return;}if (mCheckedId != -1) {setCheckedStateForView(mCheckedId, false);}if (id != -1) {setCheckedStateForView(id, true);}setCheckedId(id);}private void setCheckedId(int id) {mCheckedId = id;if (mOnCheckedChangeListener != null) {mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);}}private void setCheckedStateForView(int viewId, boolean checked) {View checkedView = findViewById(viewId);if (checkedView != null && checkedView instanceof CompoundButton) {((CompoundButton) checkedView).setChecked(checked);}}/*** <p>* Returns the identifier of the selected radio button in this group. Upon* empty selection, the returned value is -1.* </p>* * @return the unique id of the selected radio button in this group* * @see #check(int)* @see #clearCheck()* * @attr ref android.R.styleable#CustomNestRadioGroup_checkedButton*/public int getCheckedRadioButtonId() {return mCheckedId;}/*** <p>* Clears the selection. When the selection is cleared, no radio button in* this group is selected and {@link #getCheckedRadioButtonId()} returns* null.* </p>* * @see #check(int)* @see #getCheckedRadioButtonId()*/public void clearCheck() {check(-1);}/*** <p>* Register a callback to be invoked when the checked radio button changes* in this group.* </p>* * @param listener*            the callback to call on checked state change*/public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {mOnCheckedChangeListener = listener;}/*** {@inheritDoc}*/@Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs) {return new CebReadioGroup.LayoutParams(getContext(), attrs);}/*** {@inheritDoc}*/@Overrideprotected boolean checkLayoutParams(ViewGroup.LayoutParams p) {return p instanceof CebReadioGroup.LayoutParams;}@Overrideprotected LinearLayout.LayoutParams generateDefaultLayoutParams() {return new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);}/*** <p>* This set of layout parameters defaults the width and the height of the* children to {@link #WRAP_CONTENT} when they are not specified in the XML* file. Otherwise, this class ussed the value read from the XML file.* </p>* * <p>* See {@link android.R.styleable#LinearLayout_Layout LinearLayout* Attributes} for a list of all child view attributes that this class* supports.* </p>* */public static class LayoutParams extends LinearLayout.LayoutParams {/*** {@inheritDoc}*/public LayoutParams(Context c, AttributeSet attrs) {super(c, attrs);}/*** {@inheritDoc}*/public LayoutParams(int w, int h) {super(w, h);}/*** {@inheritDoc}*/public LayoutParams(int w, int h, float initWeight) {super(w, h, initWeight);}/*** {@inheritDoc}*/public LayoutParams(ViewGroup.LayoutParams p) {super(p);}/*** {@inheritDoc}*/public LayoutParams(MarginLayoutParams source) {super(source);}/*** <p>* Fixes the child's width to* {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and the* child's height to* {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} when not* specified in the XML file.* </p>* * @param a*            the styled attributes set* @param widthAttr*            the width attribute to fetch* @param heightAttr*            the height attribute to fetch*/@Overrideprotected void setBaseAttributes(TypedArray a, int widthAttr,int heightAttr) {if (a.hasValue(widthAttr)) {width = a.getLayoutDimension(widthAttr, "layout_width");} else {width = WRAP_CONTENT;}if (a.hasValue(heightAttr)) {height = a.getLayoutDimension(heightAttr, "layout_height");} else {height = WRAP_CONTENT;}}}/*** <p>* Interface definition for a callback to be invoked when the checked radio* button changed in this group.* </p>*/public interface OnCheckedChangeListener {/*** <p>* Called when the checked radio button has changed. When the selection* is cleared, checkedId is -1.* </p>* * @param group*            the group in which the checked radio button has changed* @param checkedId*            the unique identifier of the newly checked radio button*/public void onCheckedChanged(CebReadioGroup group, int checkedId);}private class CheckedStateTracker implementsCompoundButton.OnCheckedChangeListener {public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {// prevents from infinite recursionif (mProtectFromCheckedChange) {return;}mProtectFromCheckedChange = true;if (mCheckedId != -1) {setCheckedStateForView(mCheckedId, false);}mProtectFromCheckedChange = false;int id = buttonView.getId();setCheckedId(id);}}/*** <p>* A pass-through listener acts upon the events and dispatches them to* another listener. This allows the table layout to set its own internal* hierarchy change listener without preventing the user to setup his.* </p>*/private class PassThroughHierarchyChangeListener implementsViewGroup.OnHierarchyChangeListener {private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener;/*** {@inheritDoc}*/@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)public void onChildViewAdded(View parent, View child) {if (parent == CebReadioGroup.this) {CompoundButton view = findCheckedView(child);// 查找子控件if (view != null) {int id = view.getId();// generates an id if it's missingif (id == View.NO_ID&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {id = View.generateViewId();view.setId(id);}view.setOnCheckedChangeListener(mChildOnCheckedChangeListener);}}if (mOnHierarchyChangeListener != null) {mOnHierarchyChangeListener.onChildViewAdded(parent, child);}}/*** {@inheritDoc}*/public void onChildViewRemoved(View parent, View child) {if (parent == CebReadioGroup.this) {CompoundButton view = findCheckedView(child);// 查找子控件if (view != null) {view.setOnCheckedChangeListener(null);}}if (mOnHierarchyChangeListener != null) {mOnHierarchyChangeListener.onChildViewRemoved(parent, child);}}}
}

这篇关于自定义RadioGrop,支持添加包裹着的RadioButton的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1131164

相关文章

华为鸿蒙HarmonyOS 5.1官宣7月开启升级! 首批支持名单公布

《华为鸿蒙HarmonyOS5.1官宣7月开启升级!首批支持名单公布》在刚刚结束的华为Pura80系列及全场景新品发布会上,除了众多新品的发布,还有一个消息也点燃了所有鸿蒙用户的期待,那就是Ha... 在今日的华为 Pura 80 系列及全场景新品发布会上,华为宣布鸿蒙 HarmonyOS 5.1 将于 7

如何自定义一个log适配器starter

《如何自定义一个log适配器starter》:本文主要介绍如何自定义一个log适配器starter的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求Starter 项目目录结构pom.XML 配置LogInitializer实现MDCInterceptor

Druid连接池实现自定义数据库密码加解密功能

《Druid连接池实现自定义数据库密码加解密功能》在现代应用开发中,数据安全是至关重要的,本文将介绍如何在​​Druid​​连接池中实现自定义的数据库密码加解密功能,有需要的小伙伴可以参考一下... 目录1. 环境准备2. 密码加密算法的选择3. 自定义 ​​DruidDataSource​​ 的密码解密3

spring-gateway filters添加自定义过滤器实现流程分析(可插拔)

《spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔)》:本文主要介绍spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔),本文通过实例图... 目录需求背景需求拆解设计流程及作用域逻辑处理代码逻辑需求背景公司要求,通过公司网络代理访问的请求需要做请

Spring Security自定义身份认证的实现方法

《SpringSecurity自定义身份认证的实现方法》:本文主要介绍SpringSecurity自定义身份认证的实现方法,下面对SpringSecurity的这三种自定义身份认证进行详细讲解,... 目录1.内存身份认证(1)创建配置类(2)验证内存身份认证2.JDBC身份认证(1)数据准备 (2)配置依

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定

SpringKafka消息发布之KafkaTemplate与事务支持功能

《SpringKafka消息发布之KafkaTemplate与事务支持功能》通过本文介绍的基本用法、序列化选项、事务支持、错误处理和性能优化技术,开发者可以构建高效可靠的Kafka消息发布系统,事务支... 目录引言一、KafkaTemplate基础二、消息序列化三、事务支持机制四、错误处理与重试五、性能优

如何自定义Nginx JSON日志格式配置

《如何自定义NginxJSON日志格式配置》Nginx作为最流行的Web服务器之一,其灵活的日志配置能力允许我们根据需求定制日志格式,本文将详细介绍如何配置Nginx以JSON格式记录访问日志,这种... 目录前言为什么选择jsON格式日志?配置步骤详解1. 安装Nginx服务2. 自定义JSON日志格式各

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

基于Spring实现自定义错误信息返回详解

《基于Spring实现自定义错误信息返回详解》这篇文章主要为大家详细介绍了如何基于Spring实现自定义错误信息返回效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录背景目标实现产出背景Spring 提供了 @RestConChina编程trollerAdvice 用来实现 HTT