您的位置:首页 > 其它

探索RadioGroup下可否添加子Layout

2015-04-11 15:13 363 查看
创新杯的故事= =

阳光明媚的一天就这样开始了。

想写一个5*2的选择按钮,

用button,实现radiobutton的效果比较麻烦,而用radiobutton,写好之后发现radiogroup如果嵌套layout,就失去了他的功能。于是开始边寻思边折腾。

radiogroup明显是一个继承了viewgroup的layout,相信大家都看过下图,但他为何不能嵌套另一个viewgroup。。真是百思不得其姐。



(此处挠头半小时。)

我机智的决定去看android 的源码,

发现android自带的RadioGroup是继承自LinearLayout,如果布局的时候不是直接写radiobutton,即radiobutton外面还包了一层容器,这时分组是不成功的,因为查找不到radiobutton。

觉得问题在于addView方法和自定义的PassThroughHierarchyChangeListener,因为他们都是直接getchild来找radiobutton的。

下面就这两个地方动手脚,先拷贝源码,然后去掉

RadioGroup(Context context, AttributeSet attrs)


新增我们需要的方法用来查找viewGroup控件中的radioButton

/**
* @author Mr Seven
* watch out ! view group can only have one layer of layout
* @param group
* @return
*/
public ArrayList<RadioButton> findRadioButton(ViewGroup group) {
//find all child that is radiobutton
ArrayList<RadioButton> btnList = new ArrayList<RadioButton>();
int len = group.getChildCount();
for (int i = 0; i < len; i++) {
if (group.getChildAt(i) instanceof RadioButton) {
btnList.add((RadioButton) group.getChildAt(i));
} else if (group.getChildAt(i) instanceof ViewGroup) {
ArrayList<RadioButton> subList = findRadioButton((ViewGroup) group
.getChildAt(i));
for (int j = 0; j < subList.size(); j++) {
btnList.add(subList.get(j));
}
}
}
return btnList;
}


能找到所有radiogroup下的radiobutton,剩下的就好办了。

public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (child instanceof RadioButton) {
final RadioButton button = (RadioButton) child;
if (button.isChecked()) {
mProtectFromCheckedChange = true;
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;
setCheckedId(button.getId());
}

super.addView(child, index, params);

}
//this block is new
// child is a layout
else if (child instanceof ViewGroup) {
final ArrayList<RadioButton> buttonList = findRadioButton((ViewGroup) child);
for(int i = 0 ; i < buttonList.size();i++){
final RadioButton button = buttonList.get(i);
if (button.isChecked()) {
mProtectFromCheckedChange = true;
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;
setCheckedId(button.getId());
}
super.addView(button, index, params);
}//for's circulation end
}
}


等等。。。

写到这里我意识到了一个错误。。

对,就是这一行

super.addView(button, index, params);


wtf。。。他有一个index参数。。。而我们在自己的方法里找到的radiobutton并不能动态的分配给他index,也就是这样写应该显示是正常的。。但是如果你想添加个clicklistener估计就跪了,因为粑粑分不清他儿子在哪。

too young

改吧,

public RadioButton findRadioButton(ViewGroup group) {
RadioButton resBtn = null;
int len = group.getChildCount();
for (int i = 0; i < len; i++) {
if (group.getChildAt(i) instanceof RadioButton) {
resBtn = (RadioButton) group.getChildAt(i);
} else if (group.getChildAt(i) instanceof ViewGroup) {
findRadioButton((ViewGroup) group.getChildAt(i));
}
}
return resBtn;
}


既然不能找一次返回多个radiobutton,那就一次返回一个吧。

ctrl+f 找到所有他需要radiobutton的地方 都要加else if 判断child是否是一个radiobutton,比如下边的OnHierarchyChangeListener

private class PassThroughHierarchyChangeListener implements
ViewGroup.OnHierarchyChangeListener {
private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener;

public void onChildViewAdded(View parent, View child) {
if (parent == MyRadioGroup.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 == MyRadioGroup.this
&& child instanceof ViewGroup) {
RadioButton btn = findRadioButton((ViewGroup) child);
int id = btn.getId();
// generates an id if it's missing
if (id == View.NO_ID) {
id = btn.hashCode();
btn.setId(id);
}
btn.setOnCheckedChangeListener(mChildOnCheckedChangeListener);
}
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewAdded(parent, child);
}
}


已经可以三百六十度无死角地不会unfortunately,yo
9ddf
ur lancher has stopped!

hhh,但是发现这么写缺点是 一个layout下只能包含一个radiobutton。

但是已经可以实现很多想要的布局了,比如



但是并不能满足我的需求。。

too naive

发觉此路不通。

换吧

(挠头半小时)

那不如我们自定义他子view的布局好了!!!

自定义view三宝:重载onMeasure(),onLayout(),onDraw()。

那我们就改他的onMeasure(),onLayout()。

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
int childCount = getChildCount();

for (int index = 0; index < childCount; index++) {
final View child = getChildAt(index);
if (child.getVisibility() != View.GONE) {
child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
}
}
}
// 设置容器所需的宽度和高度
setMeasuredDimension(maxWidth, maxHeight);
parentHeight = maxHeight;
parentWidth = maxWidth;
childWidth = parentWidth/5;
childHeight = parentHeight / 2;
}


其实上边挺费的。。就是拿一下childwidth和childheight,可能有的代码并没有用,改来改去也没删。重点是改子view:

protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int childCount = getChildCount();
int maxWidth = r - l;
int x = 0;
int y = 0;
int row = 0;
for (int i = 0; i < childCount; i++) {
final View child = this.getChildAt(i);
if (child.getVisibility() != View.GONE) {
//                int width = child.getMeasuredWidth();
//                int height = child.getMeasuredHeight();
int width = childWidth;
int height = childHeight;
x += width;
y = row * height + height;
if (i == 5) {
x = width;
row++;
y = row * height + height;
}
child.layout(x - width, y - height, x, y);
}
}
}


快试试吧~~



好了,完美了~



余晖洒在旁边的同学吃完的橙子皮上
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  radiogroup 布局