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

相关文章

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

Oracle type (自定义类型的使用)

oracle - type   type定义: oracle中自定义数据类型 oracle中有基本的数据类型,如number,varchar2,date,numeric,float....但有时候我们需要特殊的格式, 如将name定义为(firstname,lastname)的形式,我们想把这个作为一个表的一列看待,这时候就要我们自己定义一个数据类型 格式 :create or repla

HTML5自定义属性对象Dataset

原文转自HTML5自定义属性对象Dataset简介 一、html5 自定义属性介绍 之前翻译的“你必须知道的28个HTML5特征、窍门和技术”一文中对于HTML5中自定义合法属性data-已经做过些介绍,就是在HTML5中我们可以使用data-前缀设置我们需要的自定义属性,来进行一些数据的存放,例如我们要在一个文字按钮上存放相对应的id: <a href="javascript:" d

一步一步将PlantUML类图导出为自定义格式的XMI文件

一步一步将PlantUML类图导出为自定义格式的XMI文件 说明: 首次发表日期:2024-09-08PlantUML官网: https://plantuml.com/zh/PlantUML命令行文档: https://plantuml.com/zh/command-line#6a26f548831e6a8cPlantUML XMI文档: https://plantuml.com/zh/xmi

Golang支持平滑升级的HTTP服务

前段时间用Golang在做一个HTTP的接口,因编译型语言的特性,修改了代码需要重新编译可执行文件,关闭正在运行的老程序,并启动新程序。对于访问量较大的面向用户的产品,关闭、重启的过程中势必会出现无法访问的情况,从而影响用户体验。 使用Golang的系统包开发HTTP服务,是无法支持平滑升级(优雅重启)的,本文将探讨如何解决该问题。 一、平滑升级(优雅重启)的一般思路 一般情况下,要实现平滑

sqlite不支持中文排序,采用java排序

方式一 不支持含有重复字段进行排序 /*** sqlite不支持中文排序,改用java排序* 根据指定的对象属性字段,排序对象集合,顺序* @param list* @param field* @return*/public static List sortListByField(List<?> list,String field){List temp = new ArrayList(

argodb自定义函数读取hdfs文件的注意点,避免FileSystem已关闭异常

一、问题描述 一位同学反馈,他写的argo存过中调用了一个自定义函数,函数会加载hdfs上的一个文件,但有些节点会报FileSystem closed异常,同时有时任务会成功,有时会失败。 二、问题分析 argodb的计算引擎是基于spark的定制化引擎,对于自定义函数的调用跟hive on spark的是一致的。udf要通过反射生成实例,然后迭代调用evaluate。通过代码分析,udf在

一款支持同一个屏幕界面同时播放多个视频的视频播放软件

GridPlayer 是一款基于 VLC 的免费开源跨平台多视频同步播放工具,支持在一块屏幕上同时播放多个视频。其主要功能包括: 多视频播放:用户可以在一个窗口中同时播放任意数量的视频,数量仅受硬件性能限制。支持多种格式和流媒体:GridPlayer 支持所有由 VLC 支持的视频格式以及流媒体 URL(如 m3u8 链接)。自定义网格布局:用户可以配置播放器的网格布局,以适应不同的观看需求。硬