自定義ViewGroup的基本流程
重寫兩個方法和LayoutParams
onMeasure()
通過measureChildren()來通知每一個子View自己測量(遍歷子View)卖陵。我們只需要考慮ViewGroup的寬高在自適應的情況下該是多大。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
MarginLayoutParams params = null;//布局參數(shù)
int widthMode = MeasureSpec.getMode(widthMeasureSpec);//測量兩元素Mode和Size
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
measureChildren(widthMeasureSpec,heightMeasureSpec);//遍歷子View
//開始處理wrap_content,如果一個子元素都沒有,就設置為0
if (getChildCount() == 0) {
setMeasuredDimension(0,0);
} else if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
//ViewGroup麻诀,寬掌动,高都是wrap_content糙麦,根據(jù)我們的需求吆鹤,寬度是子控件的寬度宝泵,高度則是所有子控件的總和
View childOne = getChildAt(0);
params = (MarginLayoutParams) childOne.getLayoutParams();
int childWidth = childOne.getMeasuredWidth();
int childHeight = childOne.getMeasuredHeight();
setMeasuredDimension(childWidth + params.leftMargin + params.rightMargin,
childHeight * getChildCount() + params.topMargin + params.bottomMargin);
} else if (widthMode == MeasureSpec.AT_MOST) {
//ViewGroup的寬度為wrap_content,則高度不需要管好啰,寬度還是自控件的寬度
View childOne = getChildAt(0);
params = (MarginLayoutParams) childOne.getLayoutParams();
int childWidth = childOne.getMeasuredWidth();
setMeasuredDimension(childWidth + params.leftMargin + params.rightMargin,heightSize);
} else if (heightMode == MeasureSpec.AT_MOST) {
//ViewGroup的高度為wrap_content,則寬度不需要管,高度為子View的高度和
View childOne = getChildAt(0);
params = (MarginLayoutParams) childOne.getLayoutParams();
int childHeight = childOne.getMeasuredHeight();
setMeasuredDimension(widthSize, childHeight * getChildCount() + params.topMargin + params.bottomMargin);
}
}
onLayout()
擺放子View的位置
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int height = 0;
int count = getChildCount();
View child;
Log.e("ri", count + "");
child = getChildAt(0);
MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
int c1 = params.leftMargin;
int c2 = params.topMargin;
int c3 = c1 + child.getMeasuredWidth();
int c4 = c2 + child.getMeasuredHeight();
child.layout(c1,c2, c3,c4);
height = c4 + params.bottomMargin;
for(int i = 1 ;i < count;i++) {
child = getChildAt(i);
child.layout(c1, height, c3, height + child.getMeasuredHeight());
height += child.getMeasuredHeight();
}
}
params = (MarginLayoutParams) child.getLayoutParams();
如果重寫layoutParams相關的代碼儿奶,這樣直接轉(zhuǎn)換會出現(xiàn)問題框往,所以需要重寫下面的代碼:返回MarginLayoutParams類型的對象。
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(),attrs);
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new MarginLayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
}
@Override
protected LayoutParams generateLayoutParams(LayoutParams p) {
return new MarginLayoutParams(p);
}
onTouchEvent 響應時間