项目源码地址: https://github.com/angcyo/FlowRadioGroup
为了更好的拥有RadioGroup的属性/方法:
1:新建一个View,继承RadioGroup
public class FlowRadioGroup extends RadioGroup
流式布局最重要的就是,测量子View 的大小和子View 的布局位置
2:重写onMeasure和onLayout方法
List<List<View>> mAllViews;//保存所有行的所有View
List<Integer> mLineHeight;//保存每一行的行高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
int width = 0, height = 0;
int lineWidth = 0, lineHeight = 0;
int childWidth = 0, childHeight = 0;
mAllViews = new ArrayList<>();
mLineHeight = new ArrayList<>();
List<View> lineViews = new ArrayList<>();
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) child.getLayoutParams();
childWidth = child.getMeasuredWidth() + params.leftMargin + params.rightMargin;
childHeight = child.getMeasuredHeight() + params.topMargin + params.bottomMargin;
if (lineWidth + childWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) {
width = Math.max(width, lineWidth);
height += lineHeight;
mLineHeight.add(lineHeight);
mAllViews.add(lineViews);
lineWidth = childWidth;
lineHeight = childHeight;
lineViews = new ArrayList<>();
} else {
lineWidth += childWidth;
lineHeight = Math.max(childHeight, lineHeight);
}
lineViews.add(child);
if (i == (count - 1)) {
width = Math.max(width, lineWidth);
height += lineHeight;
}
}
mLineHeight.add(lineHeight);
mAllViews.add(lineViews);
width += getPaddingLeft() + getPaddingRight();
height += getPaddingTop() + getPaddingBottom();
setMeasuredDimension(modeWidth == MeasureSpec.AT_MOST ? width : sizeWidth, modeHeight == MeasureSpec.AT_MOST ? height : sizeHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int top = getPaddingTop();//开始布局子view的 top距离
int left = getPaddingLeft();//开始布局子view的 left距离
int lineNum = mAllViews.size();//行数
List<View> lineView;
int lineHeight;
for (int i = 0; i < lineNum; i++) {
lineView = mAllViews.get(i);
lineHeight = mLineHeight.get(i);
for (int j = 0; j < lineView.size(); j++) {
View child = lineView.get(j);
if (child.getVisibility() == View.GONE) {
continue;
}
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) child.getLayoutParams();
int ld = left + params.leftMargin;
int td = top + params.topMargin;
int rd = ld + child.getMeasuredWidth();//不需要加上 params.rightMargin,
int bd = td + child.getMeasuredHeight();//不需要加上 params.bottomMargin, 因为在 onMeasure , 中已经加在了 lineHeight 中
child.layout(ld, td, rd, bd);
left += child.getMeasuredWidth() + params.leftMargin + params.rightMargin;//因为在 这里添加了;
}
left = getPaddingLeft();
top += lineHeight;
}
}
到此,基本上布局就可以使用了;
不过还有一个问题,就是布局不具备保存状态的能力;
所以需要重写onSaveInstanceState和onRestoreInstanceState方法;
这里不展示,项目源码中有,并且也有使用方法;
为了更灵活, 更方便使用;
可以扩张接口;
/**
* 获取选中按钮的索引,从开始, 未选中返回 -1
*/
public int getCheckedRadioButtonIndex() {
return indexOfChild(findViewById(getCheckedRadioButtonId()));
}
/**
* 获取选中按钮的文本,未选中 返回 空字符串
*/
public String getCheckedRadioButtonText() {
if (getCheckedRadioButtonId() == -1) {
return "";
}
return ((RadioButton) findViewById(getCheckedRadioButtonId())).getText().toString();
}
更多更好的扩展方法, 大家可以根据需求定制;
至此: 文章就结束了,如有疑问: QQ群:274306954 欢迎您的加入.