自定义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

相关文章

Python自定义异常的全面指南(入门到实践)

《Python自定义异常的全面指南(入门到实践)》想象你正在开发一个银行系统,用户转账时余额不足,如果直接抛出ValueError,调用方很难区分是金额格式错误还是余额不足,这正是Python自定义异... 目录引言:为什么需要自定义异常一、异常基础:先搞懂python的异常体系1.1 异常是什么?1.2

Linux中的自定义协议+序列反序列化用法

《Linux中的自定义协议+序列反序列化用法》文章探讨网络程序在应用层的实现,涉及TCP协议的数据传输机制、结构化数据的序列化与反序列化方法,以及通过JSON和自定义协议构建网络计算器的思路,强调分层... 目录一,再次理解协议二,序列化和反序列化三,实现网络计算器3.1 日志文件3.2Socket.hpp

C语言自定义类型之联合和枚举解读

《C语言自定义类型之联合和枚举解读》联合体共享内存,大小由最大成员决定,遵循对齐规则;枚举类型列举可能值,提升可读性和类型安全性,两者在C语言中用于优化内存和程序效率... 目录一、联合体1.1 联合体类型的声明1.2 联合体的特点1.2.1 特点11.2.2 特点21.2.3 特点31.3 联合体的大小1

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (

SpringBoot 异常处理/自定义格式校验的问题实例详解

《SpringBoot异常处理/自定义格式校验的问题实例详解》文章探讨SpringBoot中自定义注解校验问题,区分参数级与类级约束触发的异常类型,建议通过@RestControllerAdvice... 目录1. 问题简要描述2. 异常触发1) 参数级别约束2) 类级别约束3. 异常处理1) 字段级别约束

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

一文详解Java Stream的sorted自定义排序

《一文详解JavaStream的sorted自定义排序》Javastream中的sorted方法是用于对流中的元素进行排序的方法,它可以接受一个comparator参数,用于指定排序规则,sorte... 目录一、sorted 操作的基础原理二、自定义排序的实现方式1. Comparator 接口的 Lam

k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)

《k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)》本文记录在K8s上运行的MySQL/MariaDB备份方案,通过工具容器执行mysqldump,结合定时任务实... 目录前言一、获取需要备份的数据库的信息二、备份步骤1.准备工作(X86)1.准备工作(arm)2.手

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

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