您的位置:首页 > 移动开发 > Android开发

android自定义ViewGroup之瀑布流FlowLayout 简洁明了 支持padding和margin 100行代码搞定

2016-10-18 13:21 555 查看
FlowLayout完美解决购物类app参差不齐的标签、热门搜索等:

支持padding和margin

支持xml和java代码动态添加childView

简洁明了100行代码

效果图



核心代码

1、重写onMeasure:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取测量模式和测量父容器推荐宽高
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
MarginLayoutParams cParams;
int width = 0;//用于保存最大宽度
int height = 0;//用于保存最大高度,累加
int lineWidth = 0;//当前行最大宽度,累加行宽度
int lineHeight = 0;//当前行最大高度
int cCount = getChildCount();

for (int i = 0; i < cCount; i++) {
View childView = getChildAt(i);
measureChild(childView, widthMeasureSpec, heightMeasureSpec);//测量childView
cParams = (MarginLayoutParams) childView.getLayoutParams();
int leftMargin = cParams.leftMargin;
int rightMargin = cParams.rightMargin;
int topMargin = cParams.topMargin;
int bottomMargin = cParams.bottomMargin;
int cWidth = childView.getMeasuredWidth() + leftMargin + rightMargin;
int cHeight = childView.getMeasuredHeight() + topMargin + bottomMargin;
if (lineWidth + cWidth > widthSize - getPaddingLeft() - getPaddingRight()) {//如果达到换行条件
height += lineHeight;//累加高度
lineHeight = cHeight;//开启新行
width = Math.max(cWidth, lineWidth);//获取较大宽度
lineWidth = cWidth;//初始化行宽
} else {
lineHeight = Math.max(lineHeight, cHeight);//获取当前行最大高度
lineWidth += cWidth;//累加当前行宽度
}
if (i == cCount - 1) {//如果是最后一个clildView,比较width确保为最大值,累加最后一行高度
width = Math.max(width, lineWidth);
height += lineHeight;
}
}
//最后加上父容器padding
width += getPaddingLeft() + getPaddingRight();
height += getPaddingTop() + getPaddingBottom();
setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : width, heightMode == MeasureSpec.EXACTLY ? heightSize : height);
}


2、重写onLayout:

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
MarginLayoutParams cParams;
int cCount = getChildCount();
int selfWidth = getWidth();
int height = 0;//最大高累加
int lineWidth = 0;//每行最大宽累加
int lineHeight = 0;//每行最大高
for (int i = 0; i < cCount; i++) {
View childView = getChildAt(i);
if (childView.getVisibility() == View.GONE) {
continue;
}
cParams = (MarginLayoutParams) childView.getLayoutParams();
int leftMargin = cParams.leftMargin;
int rightMargin = cParams.rightMargin;
int topMargin = cParams.topMargin;
int bottomMargin = cParams.bottomMargin;
int cWidth = childView.getMeasuredWidth() + leftMargin + rightMargin;
int cHeight = childView.getMeasuredHeight() + topMargin + bottomMargin;
int cl = 0, ct = 0, cr = 0, cb = 0;//childView上左、下右2个点
if (lineWidth + cWidth > selfWidth - getPaddingLeft() - getPaddingRight()) {//如果换行
height += lineHeight;//累加高度
lineHeight = cHeight;//开启新行
lineWidth = cWidth;//重置行宽
cl = getPaddingLeft() + leftMargin;
ct = getPaddingTop() + height + topMargin;
cr = getPaddingLeft() + cWidth - rightMargin;
cb = getPaddingTop() + height + cHeight - bottomMargin;
} else {
lineHeight = Math.max(cHeight, lineHeight);//获取较大的行高
lineWidth += cWidth;//累加行宽
cl = getPaddingLeft() + lineWidth - cWidth + leftMargin;
ct = getPaddingTop() + height + topMargin;
cr = getPaddingLeft() + lineWidth - rightMargin;
cb = getPaddingTop() + height + cHeight - bottomMargin;
}
childView.layout(cl, ct, cr, cb);
}
}


3、由于ViewGroup支持margin属性,必须重写generateLayoutParams和generateDefaultLayoutParams,否则会出现classcastexception错误

@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}

@Override
protected LayoutParams generateDefaultLayoutParams() {
return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}

@Override
protected LayoutParams generateLayoutParams(LayoutParams p) {
return new MarginLayoutParams(p);
}


好了,就这么简单,代码仔细看应该都能看懂,主要是一些计算。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息