SeniorUI02_UI绘制流程分析二(View的绘制过程)
1 Effect picture
2 Demo
3 RequireMent
(1)瀑布流添加标签,图片或其他View均可;
(2)宽度相等,高度不定;
(3)每次添加元素加到最低高度的列上;
4 Theory
(1)自定义控件继承ViewGroup
(2) onMesure确定宽高,并记录每列高度
(3)定义一个Param,onMesure时记录每个child的位置
(4)onLayout中获取Param,设置每个child的位置
4 核心代码
onMesure:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//得到总宽度
int measureWidth = 0;
int measureHeight = 0;
if (widthMode == MeasureSpec.EXACTLY) {
measureWidth = widthSize;
measureHeight = heightSize;
} else {
measureChildren(widthMeasureSpec, heightMeasureSpec);
//得到单个Item的宽度
mChildWidth = (widthSize - (mColumns - 1) * mHorizontalSpace) / mColumns;
int childCount = getChildCount();
if (childCount < mColumns) {
measureWidth = childCount * mChildWidth + (childCount - 1) * mHorizontalSpace;
} else {
measureWidth = widthSize;
}
clearTop();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
int childHeight = child.getMeasuredHeight() * mChildWidth / child.getMeasuredWidth();
int minColum = getMinHeightColum();
WaterfallLayoutParams lParams = (WaterfallLayoutParams) child.getLayoutParams();
lParams.left = minColum * (mChildWidth + mHorizontalSpace);
lParams.top = mTop[minColum];
lParams.right = lParams.left + mChildWidth;
lParams.bottom = lParams.top + childHeight;
mTop[minColum] += mVerticalSpace + childHeight;
}
measureHeight = getMaxHeight();
}
setMeasuredDimension(measureWidth, measureHeight);
}
onLayout:
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();
clearTop();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
WaterfallLayoutParams params = (WaterfallLayoutParams) child.getLayoutParams();
child.layout(params.left, params.top, params.right, params.bottom);
}
}
定义一个记录child位置的params
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new WaterfallLayoutParams(getContext(), attrs);
}
public static class WaterfallLayoutParams extends LayoutParams {
public int left, top, right, bottom;
public WaterfallLayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
}
public WaterfallLayoutParams(int width, int height) {
super(width, height);
}
public WaterfallLayoutParams(LayoutParams source) {
super(source);
}
}