Android 自定義View(2)

一個View要顯示在界面上,需要經歷一個View樹的遍歷過程,這個過程又可以分爲三個過程,也就是自定義View中的三要素:大小,位置,畫什麼,即onMesure(),onLayout(),onDraw()。

onMesure()確定一個View的大小;
onLayout()確定View在父節點上的位置;
onDraw()繪製View 的內容;

這個過程的啓動是由ViewRoot.performTraversals()函數發起的,子View也可以通過一些方法來請求重新遍歷View樹,但是在遍歷過程View樹時並不是所有的View都需要重新測量,佈局和繪製,在View樹的遍歷過程中,系統會判斷View是否需要重新繪製,如果需要纔會真的去繪製View。

一、onMesure()
這個方法會被View中的measure方法調用,並且傳入經過父視圖View計算得到的widthMeasureSpec和heightMeasureSpec,即控件的寬和高。這2個參數也將確定控件寬高的規格specMode。調用MeasureSpec.getMode(widthMeasureSpec)將得到specMode:測量模式。specMode有3種類型:
1.EXACTLY
一般是march_parent或者設置了明確大小;
2.AT_MOST
一般爲warp_content,表示大小限制在一定值內,最大爲父View的大小;
3.UNSPECIFIED
一般較少使用,表示任意大小。
之後,根據得到的類型,設置自己想要的寬高,調用setMeasuredDimension(widthMeasureSpec,heightMeasureSpec)將寬高設定,控件的寬高就確定了。
注:只有在setMeasuredDimension()方法調用後,視圖大小才確定,getMeasuredWidth()和getMeasuredHeight()才能得到正確的值。

對於View.onMesure():一般的流程是:
獲取測量尺寸和模式,定義臨時變量存儲結果
判斷測量模式: specMode
是EXACTL,就使用測量規格中的尺寸;
是UNSPECIFIED,就使用自身計算的尺寸;
是AT_MOST,就使用自身計算的尺寸與規定尺寸中較小的一個;
最後,設置測量尺寸setMeasuredDimension;

對於ViewGroup.onMesure():這個情況比較多,一般根據具體情況判斷怎麼設置大小;

二、onLayout()
這個方法一般會在自定義View繼承ViewGroup的時候需要重寫的方法。

在onLayout()方法之後,getWidth()和getHeight()才能獲取到視圖的寬高。

三、onDraw()
顧名思義,這是繪製視圖的方法。一般流程是:
ViewRoot調用DecorView的draw()方法:ViewRoot–>DecorView.draw(canvas)
- DecorView的draw()方法調用自己的dispatchDraw(Canvas canvas)方法,然後在此方法中會調用子view的draw(Canvas canvas, ViewGroup parent, long drawtime)方法,此方法會調用單個參數的draw(Canvas canvas)方法。

draw的流程:
1. 繪製該View 的背景;
2. 爲顯示漸變框做一些準備操作 (一般不需要改漸變框);
3. 調用onDraw繪製內容 (ViewGroup不需要實現該方法);
4. 調用dispatchDraw繪製子View ;

onDraw是每個View需要實現的,否則View默認只能顯示背景,而實現onDraw就是爲了畫出View的內容,而ViewGroup一般不需要實現onDraw,因爲它僅僅是作爲View的容器沒有需要繪製東西,
dispatchDraw用來遍歷ViewGrop的所有子View,執行draw方法。

最後,系統給了我們多種draw的實現方法,具體暫時不記了。

Canvas畫布;
Paint 畫筆;

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