View的繪製流程簡述

onMeasure


View的繪製流程是從ViewRoot(繼承Handler)的performTraversals中內部調用measure方法開始

measure() 方法接收widthMeasureSpec和heightMeasureSpec兩個參數,兩個參數由performTravelsals內部getRootMeasureSpec得到

MeasureSpec由specSize和SpecMode組成,SpecMode有三種類型:EXACTLY、AT_MOST以及不常用的UNSPECIFIED

measure方法是final的,其中的onMeasure纔可以重寫。真正執行測量的是onMeasure()方法,如果不重寫,默認會調用getDefaultSize獲取系統測量的默認大小,setMeasureDimension設置

注意:setMeasureDimension之後才能getMeasureWidth、getMeasureHeight

補充:ViewGroup定義了measureChildren遍歷子視圖-->逐個調用measureChild-->獲取各自的MeasureSpec,調用measure(childWidthMeasreSpec,childHeightSpec)


onLayout


measure過程結束後,VieRoot的performTraversals在measure()方法結束後繼續執行,通過調用VIew的layout()方法執行,layout()接收左上右下四個座標參數,代表在父視圖中的位置

layout方法首先調用setFrame()方法判斷視圖大小是否發生變化,是否需要重繪視圖,同時將接收的四個座標賦值給mLeft、mTop、mRight、mBottom,接着調用的onLayout方法;

View的onLayout方法是一個空方法,因爲確定視圖的佈局位置應該是由佈局完成,由父視圖決定子視圖的位置,然而ViewGroup的onLayout方法是一個抽象方法,像LInearLayout、RelativeLayout都是重寫了這個方法;

注意:getMeasureWidth和getWidth的區別:getMeasureWidth在measure過程結束後獲取,getWidth在layout過程結束後獲取;getMeasureWidth通過setMeasureDimension設置,getWidth通過視圖右邊的座標減去左邊的座標計算得到;

一般是一樣的值,如果在layout過程中不用measure()獲得設定的寬高,等於忽視measure過程的計算結構,會不一樣,這樣也沒有太大


onDraw


這裏才真正開始對視圖進行繪製,VIewRoot的代碼繼續執行創建畫布對象Canvas,調用View的draw()方法執行具體的繪製;

draw(Canvas canvas)首先獲取mBGDrawable對象繪製背景:這個對象就是從XML中通過background屬性設置的圖片或顏色

接着調用onDraw()方法繪製視圖內容:onDraw是個空方法,因爲每個視圖內容不同,一般交給子類實現:如TextView、ImageView都重寫onDraw()方法

接着調用dispatchDraw()對當前視圖的子視圖繪製:而VIew中的dispatchDraw方法又是一個空方法,ViewGroup的dispatchDraw()方法就會有具體的繪製代碼

最後onDrawScrollBars()繪製視圖的滾動條

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章