標籤:github tle 視窗 取出 line mos cep 傳遞 源碼
- 3.1 Android控制項架構
- 3.2 View的測量
- 3.3 View的繪製
- 3.4 ViewGroup的測量
- 3.5 ViewGroup的繪製
- 3.6 自訂View
- 3.6.1 對現有的空間進行拓展
- 3.6.2 建立複合控制項
- 3.6.3 重寫View來實現全新的空間
- 3.7 自訂ViewGroup
- 3.8 事件攔截機制分析
控制項大致非為兩類:
- view控制項:視圖控制項
- viewGroup控制項:包含多個View控制項,並管理其包含的View控制項
- 兩者之間的關係:上層控制項負責下層子控制項的測量與繪製,並傳遞互動事件
UI介面架構:
- Activity都包含一個Window對象,通常由PhoneWindow來實現
- PhoneWindow將一個DecorView設定為整個應用視窗的根View
- DecorView為整個Window介面的最頂層View
- DecorView只有一個子項目為LinearLayout,代表整個Window介面,包含通知欄,標題列,內容顯示欄三塊地區
- LinearLayout裡有兩個FrameLayout子項目:
- 標題列顯示介面。只有一個TextView顯示應用的名稱
- 內容欄顯示介面。就是setContentView()方法載入的布局介面
MeasureSpec類:32位的int值,高2位為測量模式,低30位為測量大小
MeasureSpec模式:
- EXACTLY:精確模式 ,當控制項的layout_width屬性或layout_height屬性指定為具體值,控制項大小也是該具體值
- AT_MOST:最大值模式,當控制項layout_width屬性或layout_height屬性指定為warp_content時,控制項的尺寸不要超過父控制項允許的最大尺寸
- UNSPECIFIED:未指定模式,控制項要多大就多大,通常情況下再繪製自訂View中才會使用
View類預設的onMeasure()方法只支援EXACTLY模式,View需要支援warp_content屬性,那麼就必須重寫onMeasure()方法,來制定warp_content的大小
下面我們通過一個簡單的執行個體,示範如何進行View的測量,首先,需要重寫onMeasure()方法:
可以發現,onMeasure方法調用了父類的onMeasure方法,代碼跟蹤父類onMeasure方法
可以發現,系統最終會調用setMeasuredDimension(int measuredWidth,int measuredHeight)方法將測量後的寬高值設定進去,我們調用自訂的measureWidth()方法和measureHeight()方法,分別對寬高進行重新定義
下面以measureWidth()方法為例:
第一步:從MeasureSpec對象中提取出具體的測量模式和大小
第二步:通過不同的測量模式給出不同的測量值:
- EXACTLY:使用指定的specSize即可
- AT_MOST:取出我們指定的大小和SpecSize的最小值
- UNSPECIFIED:200px
下面這段代碼基本上可以作為模板代碼:
可以發現,當指定warp_content屬性時,View就獲得一個預設值200px
當測量好了一個View之後,我們通過重寫View類中的onDraw()方法來繪圖,要想繪製相應的映像,就必須在Canvas上進行繪製
Canvas就像是一個畫板,我們傳進去一個bitmap,通過這個bitmap建立的Canvas畫布緊緊聯絡在一起,這個過程我們稱之為裝載畫布,這個bitmap用來儲存所有繪製在Canvas上的像素資訊,所以當你在後面調用所有的Canvas.drawxxx方法都會發生在這個bitmap上
ViewGroup在測量時通過遍曆所有子View,從而調用子View的Measure方法來獲得每一個子View的結果
ViewGroup測量完畢後,通常會去重寫onLayout()方法來控制其子View顯示位置的邏輯
ViewGroup通常不需要繪製,如果不是指定ViewGroup的背景顏色,那麼ViewGroup的onDraw()方法都不會被調用,但是,ViewGroup會使用dispatchDraw()方法來繪製子View
在View中通常有以下一些重要的回調方法:
- onFinishInflate():從XML載入組件後回調
- onSizeChanged():組件大小改變時回調
- onMeasure():回調該方法來進行測量
- onLayout():回調該方法來確定顯示的位置
- onTouchEvent():監聽到觸摸事件時回調
通常情況下,有以下三種方法來實現自訂的控制項:
- 對現有的控制項進行拓展
- 通過組合來實現新的控制項
- 重寫View來實現全新的控制項
3.6.1 對現有的控制項進行拓展
- 自訂修改TextView……見經典代碼回顧,案例一
- 閃動的文字效果……見經典代碼回顧,案例二
3.6.2 建立複合控制項
- 自訂ToolBar的實現……見經典代碼回顧,案例三
3.6.3 重寫View來實現全新的控制項
- 弧線展示圖……見經典代碼回顧,案例四
- 音頻橫條圖……見經典代碼回顧,案例五
- 自訂ViewGroup,仿ScrollView……見經典代碼回顧,案例六
事件攔截機制三個重要方法
- dispatchTouchEvent():分發事件
- onInterceptTouchEvent():攔截事件
- onTouchEvent():處理事件
舉一個例子說明事件分發機制:
- ViewGroupA:處於視圖最下層
- ViewGroupB:處於視圖中介層
- View:處於視圖最上層
正常的事件分發機制流程:
- ViewGroupA dispatchTouchEvent
- ViewGroupA onInterceptTouchEvent
- ViewGroupB dispatchTouchEvent
- ViewGroupB onInterceptTouchEvent
- View dispatchTouchEvent
- View onTouchEvent
- ViewGroupB onTouchEvent
- ViewGroupA onTouchEvent
若ViewGroupB的onInterceptTouchEvent()方法返回true的分發機制流程:
- ViewGroupA dispatchTouchEvent
- ViewGroupA onInterceptTouchEvent
- ViewGroupB dispatchTouchEvent
- ViewGroupB onInterceptTouchEvent
- ViewGroupB onTouchEvent
- ViewGroupA onTouchEvent
若View的onTouchEvent()方法返回true的分發機制流程:
- ViewGroupA dispatchTouchEvent
- ViewGroupA onInterceptTouchEvent
- ViewGroupB dispatchTouchEvent
- ViewGroupB onInterceptTouchEvent
- View dispatchTouchEvent
- View onTouchEvent
若ViewGroupB的onTouchEvent()方法返回true的分發機制流程:
- ViewGroupA dispatchTouchEvent
- ViewGroupA onInterceptTouchEvent
- ViewGroupB dispatchTouchEvent
- ViewGroupB onInterceptTouchEvent
- View dispatchTouchEvent
- View onTouchEvent
- ViewGroupB onTouchEvent
簡單的說dispatchTouchEvent()和onInterceptTouchEvent()是從下往上一層一層分發下去的,而onTouchEvent()是從上往下一層一層分發下去的
在values檔案夾中建立一個attrs.xml檔案來自訂屬性
開始建立我們的ToolBar
在布局檔案中使用
當使用者不指定具體的比例值時,可以調用以下代碼來設定相應的比例值
自訂的ScrollView沒有系統內建的效能好,畢竟很多因素都沒考慮到,這裡只是適用於練手使用
在布局中使用
經典回顧源碼下載
github:https://github.com/CSDNHensen/QunYingZhuang
Android群英傳知識點回顧——第三章:Android控制項架構與自訂控制項詳解