RadioGroup设置orientation="vertical"竖向单列显示

RadioGroup设置orientation="horizontal"横向单行显示

如何实现多行多列RadioButton呢?

step1:重写RadioGroup类

package com.hz.w504_sing_common;

import java.util.ArrayList;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.RadioButton; /** 可以放多种布局控件,能找到radiobutton */
public class FlowRadioGroup extends LinearLayout {
// holds the checked id; the selection is empty by default
private int mCheckedId = -;
// tracks children radio buttons checked state
private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
// when true, mOnCheckedChangeListener discards events
private boolean mProtectFromCheckedChange = false;
private OnCheckedChangeListener mOnCheckedChangeListener;
private PassThroughHierarchyChangeListener mPassThroughListener; // 存放当前的radioButton
private ArrayList<RadioButton> radioButtons; public FlowRadioGroup(Context context) {
super(context);
setOrientation(VERTICAL);
init();
} public FlowRadioGroup(Context context, AttributeSet attrs) {
super(context, attrs);
init();
} private void init() {
mChildOnCheckedChangeListener = new CheckedStateTracker();
mPassThroughListener = new PassThroughHierarchyChangeListener();
super.setOnHierarchyChangeListener(mPassThroughListener);
radioButtons = new ArrayList<RadioButton>();
} @Override
public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
// the user listener is delegated to our pass-through listener
mPassThroughListener.mOnHierarchyChangeListener = listener;
} @Override
protected void onFinishInflate() {
super.onFinishInflate(); // checks the appropriate radio button as requested in the XML file
if (mCheckedId != -) {
mProtectFromCheckedChange = true;
setCheckedStateForView(mCheckedId, true);
mProtectFromCheckedChange = false;
setCheckedId(mCheckedId);
}
} @Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (child instanceof RadioButton) {
final RadioButton button = (RadioButton) child;
radioButtons.add(button); if (button.isChecked()) {
mProtectFromCheckedChange = true;
if (mCheckedId != -) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;
setCheckedId(button.getId());
}
} else if (child instanceof ViewGroup) {// 如果是复合控件
// 遍历复合控件
ViewGroup vg = ((ViewGroup) child);
setCheckedView(vg);
} super.addView(child, index, params);
} /** 查找复合控件并设置radiobutton */
private void setCheckedView(ViewGroup vg) {
int len = vg.getChildCount();
for (int i = ; i < len; i++) {
if (vg.getChildAt(i) instanceof RadioButton) {// 如果找到了,就设置check状态
final RadioButton button = (RadioButton) vg.getChildAt(i);
// 添加到容器
radioButtons.add(button);
if (button.isChecked()) {
mProtectFromCheckedChange = true;
if (mCheckedId != -) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;
setCheckedId(button.getId());
}
} else if (vg.getChildAt(i) instanceof ViewGroup) {// 迭代查找并设置
ViewGroup childVg = (ViewGroup) vg.getChildAt(i);
setCheckedView(childVg);
}
}
} /** 查找复合控件并设置id */
private void setCheckedId(ViewGroup vg) {
int len = vg.getChildCount();
for (int i = ; i < len; i++) {
if (vg.getChildAt(i) instanceof RadioButton) {// 如果找到了,就设置check状态
final RadioButton button = (RadioButton) vg.getChildAt(i);
int id = button.getId();
// generates an id if it's missing
if (id == View.NO_ID) {
id = button.hashCode();
button.setId(id);
}
button.setOnCheckedChangeListener(mChildOnCheckedChangeListener);
} else if (vg.getChildAt(i) instanceof ViewGroup) {// 迭代查找并设置
ViewGroup childVg = (ViewGroup) vg.getChildAt(i);
setCheckedId(childVg);
}
}
} /** 查找radioButton控件 */
public RadioButton findRadioButton(ViewGroup group) {
RadioButton resBtn = null;
int len = group.getChildCount();
for (int i = ; i < len; i++) {
if (group.getChildAt(i) instanceof RadioButton) {
resBtn = (RadioButton) group.getChildAt(i);
} else if (group.getChildAt(i) instanceof ViewGroup) {
resBtn = findRadioButton((ViewGroup) group.getChildAt(i));
findRadioButton((ViewGroup) group.getChildAt(i));
break;
}
}
return resBtn;
} /** 返回当前radiobutton控件的count */
public int getRadioButtonCount() {
return radioButtons.size();
} /** 返回当前index的radio */
public RadioButton getRadioButton(int index) {
return radioButtons.get(index);
} /**
* <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 bother
if (id != - && (id == mCheckedId)) {
return;
} if (mCheckedId != -) {
setCheckedStateForView(mCheckedId, false);
} if (id != -) {
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 RadioButton) {
((RadioButton) 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()
*/
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(-);
} /**
* <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}
*/
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new FlowRadioGroup.LayoutParams(getContext(), attrs);
} /**
* {@inheritDoc}
*/
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof FlowRadioGroup.LayoutParams;
} @Override
protected 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
*/
@Override
protected 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(FlowRadioGroup group, int checkedId);
} private class CheckedStateTracker implements
CompoundButton.OnCheckedChangeListener {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// prevents from infinite recursion
if (mProtectFromCheckedChange) {
return;
} mProtectFromCheckedChange = true;
if (mCheckedId != -) {
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 implements
ViewGroup.OnHierarchyChangeListener {
private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener; public void onChildViewAdded(View parent, View child) {
if (parent == FlowRadioGroup.this && child instanceof RadioButton) {
int id = child.getId();
// generates an id if it's missing
if (id == View.NO_ID) {
id = child.hashCode();
child.setId(id);
}
((RadioButton) child)
.setOnCheckedChangeListener(mChildOnCheckedChangeListener);
} else if (parent == FlowRadioGroup.this
&& child instanceof ViewGroup) {// 如果是复合控件
// 查找并设置id
setCheckedId((ViewGroup) child);
} if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewAdded(parent, child);
}
} public void onChildViewRemoved(View parent, View child) {
if (parent == FlowRadioGroup.this && child instanceof RadioButton) {
((RadioButton) child).setOnCheckedChangeListener(null);
} else if (parent == FlowRadioGroup.this
&& child instanceof ViewGroup) {
findRadioButton((ViewGroup) child).setOnCheckedChangeListener(
null);
}
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
}
}
}
}

FlowRadioGroup

step2:引用FlowRadioGroup结合LinearLayout布局

<com.hz.w504_sing_common.FlowRadioGroup
android:id="@+id/radioGroup"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_marginTop="10dip"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" > <RadioButton
android:layout_width="0dip"
android:layout_weight=""
android:layout_height="wrap_content"
android:text="" />
<RadioButton
android:layout_width="0dip"
android:layout_weight=""
android:layout_height="wrap_content"
android:text="" />
<RadioButton
android:layout_width="0dip"
android:layout_weight=""
android:layout_height="wrap_content"
android:text="" />
<RadioButton
android:layout_width="0dip"
android:layout_weight=""
android:layout_height="wrap_content"
android:text="" /> </LinearLayout> <LinearLayout android:layout_marginTop="10dip"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" > <RadioButton
android:layout_width="0dip"
android:layout_weight=""
android:layout_height="wrap_content"
android:text="" />
<RadioButton android:layout_width="0dip"
android:layout_weight=""
android:layout_height="wrap_content"
android:text="" />
<RadioButton
android:layout_width="0dip"
android:layout_weight=""
android:layout_height="wrap_content"
android:text="" />
<RadioButton
android:layout_width="0dip"
android:layout_weight=""
android:layout_height="wrap_content"
android:text="" />
</LinearLayout>
</com.hz.w504_sing_common.FlowRadioGroup>

布局

哦了

最新文章

  1. [Python] 利用Django进行Web开发系列(一)
  2. php常用函数(持续中)
  3. C#中关于异步的三种写法
  4. 从零开始学Python04作业思路:模拟ATM电子银行
  5. 一次关于使用status作为变量引发的bug及思考
  6. struts复合类型传值(对象传值)
  7. 【转】statfs获得硬盘使用情况 模拟linux命令 df
  8. Android(java)学习笔记85:案例拨号程序
  9. 从JavaScript的移位运算看数字在计算机内部的编码——补码
  10. CAD 致命错误
  11. ios swift例子源码网址总结
  12. 维护爬虫代理IP池--采集并验证
  13. CTR预估算法之FM, FFM, DeepFM及实践
  14. Linux系统(本例以Ubuntu18.04为例)安装GCC编译器
  15. python中的os
  16. 企业项目开发--cookie(1)
  17. HDU1024 Max Sum Plus Plus 【DP】
  18. 安卓手机数据恢复软件-DiskDigger Pro
  19. Hadoop体系结构之 Mapreduce
  20. MITK 手册

热门文章

  1. Mac下安装m2crypto 解决找不到openssl头文件的错误
  2. ida脚本学习
  3. Python使用suds调用webservice报错解决方法:AttributeError: &#39;Document&#39; object has no attribute &#39;set&#39;
  4. ecshop 前台个人中心修改侧边栏 和 侧边栏显示不全 或 导航现实不全
  5. bat cmd 获取管理员权限
  6. UVA 10256 The Great Divide(点在多边形内)
  7. Bootstrap-全局CSS样式-图片样式
  8. 并查集(disjoint)
  9. [11]Windows内核情景分析---设备驱动
  10. DSO安装试运行