自定義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);
}