自定义viewGroup必须要实现的一个方法,实现所有子控件布局的函数,自顶向下通过计算好的尺寸放置每一个子View
首先有关getWidth()和getMeasuredWidth()的区别为:onlayout()方法内会用到
- getMeasuredWidth()是在measure过程后就可以获取到的,getWidth()是在layout()过程结束后才能获得到的
- getMeasuredWidth()中的值是子view在侧来最后使用setMeasuredDimension(width, height)来设置的,getWidth()的值是在onlayout()方法之后父view动态设置的
- setMeasuredDimension(width, height)只是先确定了给父view的一个建议宽高,子view最终的宽高还是通过childAt.layout(0,top,measuredWidth,measuredHeight+top)来设置的
- getMeasureWidth()只有在measure()过程中才可以获得,getWidth()只有在layout()之后才可以获得
如下所示:
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int lineWidth = 0;
int lineHeight = 0;
int top = 0;
int left = 0;
int count = getChildCount();
for (int i = 0; i < count; i++) {
View childAt = getChildAt(i);
MarginLayoutParams layoutParams = (MarginLayoutParams) childAt.getLayoutParams();
//得到子view的测量建议高度
int measuredHeight = childAt.getMeasuredHeight() + layoutParams.bottomMargin + layoutParams.topMargin;
int measuredWidth = childAt.getMeasuredWidth() + layoutParams.leftMargin + layoutParams.rightMargin;
//换行
if (measuredWidth + lineWidth > getMeasuredWidth()) {
top += lineHeight;
left = 0;
lineHeight = measuredHeight;
lineWidth = measuredWidth;
} else {
lineHeight = Math.max(measuredHeight, lineHeight);
lineWidth += measuredWidth;
}
//的到字view的当前位置
int ll = left + layoutParams.leftMargin;
int tt = top + layoutParams.topMargin;
int rr = ll + childAt.getMeasuredWidth();
int bb = tt + childAt.getMeasuredHeight();
//设置子view的确定位置
childAt.layout(ll, tt, rr, bb);
left += measuredWidth;
}
设置margin时需要重载的方法有:
@Override
protected LayoutParams generateLayoutParams(LayoutParams p) {
return new MarginLayoutParams(p);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(),attrs);
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new MarginLayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
}
设置子view的点击事件
/**
* 设置点击事件
*
* @param listener
*/
public void setOnItemClickListener(final OnItemClickListener listener) {
for (int i = 0; i < getChildCount(); i++) {
final int index = i;
View childAt = getChildAt(i);
childAt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick(index);
}
});
}
}
public interface OnItemClickListener {
void onItemClick(int position);
}