相關(guān)文章
android基礎(chǔ)-view的測量各吨,布局叛甫,繪制
知識點
- viewgroup的測量
- viewgroup的布局
- viewgroup的繪制
一、viewgroup的測量
viewgroup的作用主要用于管理子view谐丢,而在測量的時候可以分兩種情況
- 當viewgroup的大小設(shè)置為 wrap_content的時候 : viewgroup就需要對子view進行遍歷爽航,以便于獲取每個子view的大小,從而來決定自身大小
- 當viewgroup的大小設(shè)置為上述的其他模式的時候: 就會通過具體的大小來設(shè)置自身的大小
關(guān)于viewgroup遍歷子view去測量的方法乾忱,android中已經(jīng)幫我們封裝了兩個常用方法:
protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec)
protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed)
從方法名和方法里面不難看出這兩個方法的區(qū)別讥珍,就是后者把子view的padding和margin也考慮了進去,不過他們最終調(diào)用的都是子view的view.measure(int wSpec,int hSpec)
方法該方法回觸發(fā)子view的onMeasure
方法
最后在測量子view之后饭耳,就要對自身大小做決定了串述,同樣是根據(jù)不同的測量模式來確定最終的大小执解,并且最后需要調(diào)用
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight)
該方法來設(shè)置viewgroup的寬高
viewgroup的測量栗子如下:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//測量子view
measureChildren(widthMeasureSpec,heightMeasureSpec);
int wModeSpec=MeasureSpec.getMode(widthMeasureSpec);
int wSizeSpec=MeasureSpec.getSize(widthMeasureSpec);
//這里只做了寬的測量寞肖,高度的測量也是類似的
int resuletW=myMeasureWidth(wModeSpec,wSizeSpec);
setMeasuredDimension(resuletW,heightMeasureSpec);
}
private int myMeasureWidth(int specMode,int specSize){
int result=0;
if(specMode==MeasureSpec.EXACTLY){
//精準模式直接賦值
result=specSize;
}else if(specMode==MeasureSpec.AT_MOST){
//這里一般根據(jù)viewgroup的類型來做處理纲酗,比如framelayout,linearlayout這些類型
//對于linearlayout類可以如下
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
result += view.getMeasuredWidth();
}
//對于framelayout這種類型,我們只需取最大的就好
// for (int i = 0; i < getChildCount(); i++) {
// View view = getChildAt(i);
// result = view.getMeasuredWidth() > result ? view.getMeasuredWidth() : result;
// }
}else {
//剩余的這種模式就是沒限制大小的模式了新蟆,一般用于recyclerview這種可以擴展的布局形式
//具體的測量方法就是看實際需求了
}
return result;
}
二觅赊、viewgroup的布局
在自定義viewgroup的時候,我們必須重寫如下方法:
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
該方法主要就是通知子view去設(shè)置他們的布局位置琼稻,之前android基礎(chǔ)-view的測量吮螺,布局,繪制的篇章也已經(jīng)詳細說明了view.layout方法的過程
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 子view數(shù)目
int childCount = getChildCount();
// 垂直擺放子view
for (int i = 0;i<childCount;i++){
View childView = getChildAt(i);
int height = childView.getMeasuredHeight();
childView.layout(l, i*height, r, t + (i+1)*height);
}
//這里擺放子view的設(shè)計也是根據(jù)實際需要帕翻,這里這做個簡單的例子
}
三鸠补、viewgroup的繪制
viewgroup通知情況下不需要繪制,因為他本身就沒有需要繪制的東西嘀掸,如果不是指定了viewgroup的背景色紫岩,那么viewgroup的onDraw方法都不會被調(diào)用。但是睬塌,viewgroup會使用dispatchDraw()方法來繪制其子view泉蝌,其過程同樣是通過變遍歷所有的子view,并調(diào)用子view的繪制方法來完成繪制工作
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
}
注意對于viewgroup而言onDraw()先于dispatchDraw()執(zhí)行,用于本身控件的繪制,dispatchDraw()用于子控件的繪制揩晴,所以如果想對于viewgroup中繪制完子view之后在對其修改勋陪,我們可以在dispatchDraw調(diào)用surper方法之前做自己想要的繪制效果,這樣避免了被子view的覆蓋
總結(jié)
viewgroup的測量硫兰,布局诅愚,繪制,其實都只是用來管理和通知子view去具體實現(xiàn)劫映,可能最主要就是onLayout方法去定義子view的顯示位置呻粹,其他的核心都是在view中做處理的,所以先理解清楚view的顯示過程苏研,那么再來理解viewgroup的顯示過程等浊,就會容易理解許多
參考文章
《Android群英傳》?