View繪製基本知識點

!經過閱讀Android開發藝術探索整理html

 
底層工做原理:測量流程、佈局流程、繪製流程
 
常見回調方法:構造方法 onAttach onVisiblityChanged onDetach
 
ViewRoot對應ViewRootImpl,鏈接WindowManager與DecorView的紐帶。
performTraversals方法:完成measure、layout、draw流程
 
傳遞流程:
ViewGroup                                                                    View
1.performMearsure> mearsure>onMearsure  傳遞        measure     
2.performLayout>layout>onLayout                 傳遞       layout
3.performDraw>draw>onDraw                      傳遞        draw
 
解讀:performTraversals依次調用performMearsure,performLayout,performDraw分別完成頂層View的measure,layout,draw三大流程。其中performMearsure調用measure,measure調用onMeasure,onMeasure中對全部子元素進行measure過程,此時measure流程由父元素傳遞到子元素,完成一次measure過程。子元素會重複父元素的measure過程,如此反覆完成整個View樹遍歷。performLayout與performDraw流程相似,可是performDraw的傳遞過程是 在draw方法中經過dispatchDraw完成
 
方法做用:
measure:決定View的寬高,完成之後經過getMeasuredWidth/getMeasuredHeight獲取測量後的寬高,幾乎全部狀況等同於View的最終寬高,特殊狀況除外;
layout:View四個頂點的座標及實際的View寬、高。四點位置:getTop/getLeft/getRight/getBottom,最終寬高getWidth/getHeight;
draw:決定View 的顯示,完成後View纔會在屏幕上顯示。
 
DectorView:豎直方向包含一個LinearLayout,包含上下兩部分,標題欄,內容欄,setContentView佈局添加到內容欄,id爲content。ViewGroup conent=findViewById(R.android.id.content),獲得content;獲得咱們設置的View:conent.getChildAt(0);
 
MeasureSpec: 測量規格,32位int值 ,高兩位SpecMode 低30位SpecSize。父容器影響View的MeasureSpec建立過程。測量過程當中,系統會將View的LayoutParams根據父容器所施加的規則轉換成對應的MeasureSpec,而後再根據MeasureSpec測量View的寬高。
 
SpecMode分類: 
UNSPECIFIED: 不限定大小,通常用於系統內部表示一種測量狀態;
AT_MOST:父容器指定大小SpecSize,View不能超過該值,對應wrap_content;
EXACTLY:精確大小,就是SpecSize值,對應match_parent及具體數值
 
MeasureSpec與LayoutParams對應關係:
注意:LayoutParams需和父容器一塊兒決定View的MeasureSpec,進一步決定View的寬高
 
DecorView :由窗口尺寸與LayoutParams共同決定
規則:match_parent>EXACTLY,窗口大小
        wrap_content>AT_MOST  大小不定,但不超過窗口
        固定大小,爲LayoutParams指定
方法:ViewRootImpl中measureHierarchy方法,屏幕尺寸desireWindowWidth,desireWindowHeight getRootMeaSureSpec方法實現
 
普通View:由父容器MeasureSpec與自身LayoutParams決定,MeasureSpec一旦肯定,onMeasure就能夠肯定View的測量寬高
方法:measure以前,經過getChildMeasureSpec獲得子元素的MeasureSpec,子元素的MeasureSpec與父元素的MeasureSpec、自己的LayoutParams、padding及margin有關
 
規則:
1.當View固定寬高時,不管父容器何種MeasureSpec,View 的MeasureSpec都精確模式,大小遵循LayoutParams規定大小;
2.View寬高是match_parent時,父容器精確View也精確且大小是父容器剩餘空間;父容器最大時View也最大且大小不超過父容器剩餘空間
3.View寬高是wrap_content時,無論父容器是精確仍是最大化,View都是最大化且不超過父容器剩餘空間。
 
 
 
View工做流程:主要爲measure/layout/draw
 
View 的measure:
measure: final方法,調用onMeasure完成。
1.setMeasuredDimension方法設置View寬高測量值。
2.getDefaultSize,AT_MOST與EXACTLY模式時返回的大小就是MeasureSpec中的specSize,最後測量的大小。最終確認在layout階段,但幾乎全部狀況下View的測量大小就是最後的大小。
UNSPECFIDED模式,通常用於系統內部測量,寬/高的測量值就是getSuggestedMininumWidth/getSuggestedMininumHeight的返回值。
getSuggestedMininumWidth:若是View沒有設置背景,返回android:minWidth的值,能夠爲0;設置背景,返回android:minWidth和背景寬度中的最大值。
 
結論:直接繼承View重寫onMeasure並設置wrap_content時的大小,不然在佈局中使用的wrap_content至關於match_parent
方式:根據須要,給View指定一個默認的內部寬高,在wrap_content時設置此值,非wrap_content情形,沿用系統的測量值。
 
ViewGroup的measure:
除完成本身的measure,還需遍歷調用子元素的measure方法,各子元素遞歸執行此流程
方法:提供measureChildren方法,對每個子元素measure,經過measureChild方法取出子元素LayoutParams,經過getChildMeasureSpec建立子元素的MeasureSpec,將MeasureSpec傳遞給子元素的measure來完成測量
ViewGroup沒有定義具體的measure過程,由於是抽象類,測量過程的onMeasure須要子類去完成,不一樣的子類有不一樣的佈局特性,測量細節不一樣。
 
總結:measure完成後,經過getMeasuredWidth/Heigt就能夠正確的獲得View的測量 寬高。某些極端狀況下:系統須要屢次測量才能肯定寬高,此時onMeasure獲取寬高不許確,良好習慣是在onLayout中獲取View的測量寬高或最終寬高
 
 
layout:
做用:ViewGroup用來肯定子元素位置
概述:onLayout遍歷調用子元素layout,layout中的onLayout方法繼續調用
流程:1.setFrame方法設置View的四個頂點位置,頂點位置一旦肯定,View在父容器中的位置就會肯定;
2.調用onLayout,父容器肯定子元素位置,具體實現與具體佈局有關,View與ViewGroup沒有具體實現
 
View的測量寬高與實際寬高區別:默認實現中是相等的,測量寬高成形於View的measure過程,最終寬高造成於layout過程,兩者賦值時機不一樣。平常開發中,咱們能夠認爲測量寬高就等於最終寬高;
注:一些特殊狀況下,View會屢次測量纔會肯定本身的測量寬高,前幾回測量過程當中得出的寬高確實有可能與實際不一致,但最終,兩者會相同
 
draw:
流程:1.繪製背景 background.draw(Canvas)
2.繪製本身 onDraw
3.繪製Childrend dispatchDraw
4.繪製裝飾onDrawScrollbars
View繪製過程的傳遞經過dispathcDraw完成,dispatchDraw會遍歷調用全部子元素的draw方法,一層一層傳遞
特殊方法:setWillNotDraw,View默認沒有啓用,ViewGroup默認啓用,不繪製任何內容時,該標記設爲true,系統會進行相應優化;對咱們的意義是,當咱們自定義控件繼承自ViewGroup,自己不具有繪製功能時,能夠開啓此標記以便系統優化。明確知道ViewGroup須要經過onDraw繪製時,須要顯示關閉此標記
 
自定義View:
分類:
1.繼承View重寫onDraw :不方便經過佈局組合方式,靜態或動態顯示一些不規則圖形,需支持wrap_content,處理padding
2.繼承ViewGroup派生特殊Layout:實現自定義佈局,當幾種View組合在一塊兒時,須要合適處理measure與layout過程,同時處理子元素測量佈局過程。更接近View底層
3.繼承特殊的View如TextView:擴展已有View功能,不須要本身支持wrap_content與padding
4.繼承特殊的ViewGroup如LinearLayout:不須要處理measure與layout過程,當幾種View組合時。
 
須知:1.讓View支持wrap_content
2.若有必要,讓View支持padding
3.儘可能不在View中使用Handler,不必。除非明確須要發送消息
4.View中若是有動畫或線程,及時中止,detachedFromWindow
5.處理好滑動嵌套衝突
 
思想:首先掌握基本功,如彈性滑動,滑動衝突,繪製原理;面對新的自定義View時可以分類並選擇合適的實現思路;平時多積累自定義View的經驗,作到融匯貫通
 
轉載:http://www.apkbus.com/blog-35555-72610.html
相關文章
相關標籤/搜索