深入理解Android中View
文章目錄
[隱藏]- 一、View是什么?
- 二、View創建的一個概述:
- 三、View的標志(Flag)系統
- 四、MeasureSpec
- 五、幾個重要方法簡介
- 5.1 onFinishInflate()
- 5.2 onMeasure(int, int)
- 5.3 onLayout(boolean, int, int,int, int)
- 5.4 onSizeChanged(int, int, int,int)
- 5.5 onDraw(android.graphics.Canvas)
? 這回我們是深入到View內部,去研究View,去了解View的工作,拋棄其他因素,以便為以后能靈活的使用自定義空間打下一定的基礎。希望有志同道合的朋友一起來探討,深入Android內部,深入理解Android。
一、View是什么?
? ? ? ?View是什么了,每個人都有自己的理解。在Android的官方文檔中是這樣描述的:這個類表示了用戶界面的基本構建模塊。一個View占用了屏幕上的一個矩形區域并且負責界面繪制和事件處理。View是用來構建用戶界面組件(Button,Textfields等等)的基類。ViewGroup子類是各種布局的基類,它是個包含其他View(或其他ViewGroups)和定義這些View布局參數的容器。
? ? ? ?其實說白了,View就是一個矩形區域,我們可以在這個區域上定義自己的控件。
? ? ? ?注明:有對系統回調不太了解的回頭看看回調,這樣有助于對文章的理解。
二、View創建的一個概述:
? ? ? ?在API中對View的回調流程有以個詳細的描述,下面給出了原文翻譯:(翻譯有點倉促,大家多多包涵,有啥錯的地方麻煩告知下我,我好改過來)
? ? ? ?1.Creation ? ? ? ? ? :創建
? ? ? ? ?----Constructors(構造器) ? ?
? ? ? ?There is a form of the constructor that arecalled when the view is created from code and a form that is called when theview is inflated from a layout file. The second form should parse and apply anyattributes defined in the layout file.在構造器中有個一個表單當View從代碼中創建和從Layout File 文件中創建時。第二個表單應該解析和應用一些在Layout File中定義的屬性。
? ? ? ? ?---- onFinishInflate()
? ? ? ? Called after a view and all of itschildren has been inflated from XML.當View和他的所有子View從XML中解析完成后調用。
? ? ? ?2. Layout ? ? ? ? ? ?:布局
? ? ? ? ?----onMeasure(int, int)
? ? ? ? Called to determine the size requirementsfor this view and all of its children. ? 確定View和它所有的子View要求的尺寸時調用
? ? ? ? ?---- onLayout(boolean, int, int,int, int)
? ? ? ? Calledwhen this view should assign a size and position to all of its children當這個View為其所有的子View指派一個尺寸和位置時調用
? ? ? ? ?---- onSizeChanged(int, int, int,int)
? ? ? ? Calledwhen the size of this view has changed.當這個View的尺寸改變后調用
? ? ? ?3. Drawing ? ? ? ? :繪制
? ? ? ? ?---- onDraw(Canvas)
? ? ? ? Calledwhen the view should render its content.當View給定其內容時調用
? ? ? ?4.Event processing ? ?:事件流程
? ? ? ? ?----onKeyDown(int, KeyEvent)
? ? ? ? Calledwhen a new key event occurs.當一個新的鍵按下時
? ? ? ? ?---- onKeyUp(int, KeyEvent) ?
? ? ? ? Calledwhen a key up event occurs.當一個鍵彈起時
? ? ? ? ?----onTrackballEvent(MotionEvent)
? ? ? ? Calledwhen a trackball motion event occurs.當滾跡球事件發生時。
? ? ? ? ?----onTouchEvent(MotionEvent)
? ? ? ? Calledwhen a touch screen motion event occurs.當一個觸摸屏事件發生時。
? ? ? ?5. Focus ? ? ? ? ? ? ?:焦點
? ? ? ? ?---- onFocusChanged(boolean, int,Rect)
? ? ? ? onFocusChanged(boolean,int, Rect)當View得到和失去焦點時調用
? ? ? ? ---- onWindowFocusChanged(boolean)
? ? ? ? Called when the windowcontaining the view gains or loses focus.當Window包含的View得到或失去焦點時調用。
? ? ? ?根據View里面方法調用流程的概述,我們來重寫其中的幾個回調方法來直觀的了解下這個調用,具體代碼這里就不貼了,代碼見測試包:DEMO_View調用流程.rar,調用的log顯示:
? ? ? ?這樣大家就對View的調用有了個大概的認識,下面將針對View的標志系統、View的的布局參數系統等做一個簡單的描述。
三、View的標志(Flag)系統
? ? ? ?在一個系統中往往使用標志來指示系統中的某些參數,這里對View的標志系統做一些簡單的介紹,這樣大家可以借鑒下,以后也可以用這種表示方法。
? ? ? ?一般而言標志都是成對出現的也就是表示相反兩個屬性,對于這種屬性的表示方法我們使用一位的0和1就可以表示。如果有多個成對屬性,如果每對屬性都用一個int值來標志是不方便的。這種情況通常是用一個int的各個位來分別表示每個標志,在處理器中有一個標志位就是采用這種方式設計的。
我們先來看看位運算。位運算符包括: 與(&)、非(~)、或(|)、異或(^)
? ?&: ? 當兩邊操作數的位同時為1時,結果為1,否則為0。如1100&1010=1000
? ? ? ?|: ? 當兩邊操作數的位有一邊為1時,結果為1,否則為0。如1100|1010=1110
? ? ? ?~: ? 0變1,1變0
? ? ? ?^: ? 兩邊的位不同時,結果為1,否則為0.如1100^1010=0110
? ? ? ?在View系統使用mViewFlags來表征這些屬性,其設置的主要方法如下
[java] view plaincopy其中mask指的是標志位所在的位,falg表示的標志位。下面舉個例子:
[java] view plaincopy? ? ? ?其中VISIBLE和INVISIBLE和GONE就是標志位,VISIBILITY_MASK是標志位所在的位,也就有VISIBLE+INVISIBLE+GON=VISIBILITY_MASK。看不懂的把上面四個轉換為二進制就看出來了。
? ? ? ?為什么要使用VISIBILITY_MASK?會不會有些多余呢?我們來看View中的計算公式:
[java] view plaincopy? ? ? ?其中mViewFlags & ~mask是用來將mViewFlags中表示該標志的位置零。mask & falg是用來獲得標志位。舉個例子:
? ? ? ?假設mViewFlags的二進制表示為110000;flag為INVISIBLE我們將上面的標志位轉換為二進制VISIBLE 0000、INVISIBLE 0100、GONE 1000、VISIBILITY_MASK 1100。
mViewFlags & ~mask=110000 & 0011 = 110000(上面所用的標志位占用的是最后四位,我們通過這個運算來將這個標志位置零)。
[java] view plaincopy? ? ? ?110000 | 0100(通過或運算來計算出最后的標志)。
? ? ? ?一般而言:在多個同種類型的標志中,通常使用0來作為默認的標志。關于上面的標志系統的其他具體使用我們就不再深入,有興趣的可以自行深入,有啥好的想法在群里分享下。
四、MeasureSpec
? ? ? ?在View系統中,指定寬和高,以及指定布局的屬性,是由MeasureSpec來封裝的。下面是各個模式的標志位表示。
[java] view plaincopy? ? ? ?在這個解析系統中是通過移位來存放更多的數據,現在每個數據標志位都向左移動了30位。這樣表示一個View大小是很方便的,我們來看下面的方法:
[java] view plaincopy? ? ? ?通過這個方法就可以制作一個含有兩個參數的int值,這個參數包含一個mode標志和一個寬或高的表示。
? ? ? ?我們通過如下方法來獲取到mode:
[java] view plaincopy? ? ? ?我們也可以用下面方法來獲取高或寬的數據表示:
[java] view plaincopy五、幾個重要方法簡介
? ? ? ?正如第二節寫的那個調用流程一樣,這幾個重要的方法是系統回調是調用的,同樣對于這幾個方法也是自定義組件的重要的方法。
? ? ? ?在這節里我們主要是了解這些方法的用途,以期在自定義組件時可以對這些方法得心應手。
5.1 onFinishInflate()
? ? ? ?這個是當系統解析XML完成,并且將子View全部添加完成之后調用這個方法,我們通常重寫這個方法,在這個方法中查找并獲得子View引用,當然前提是這個View中有子View所以一般都是繼承ViewGroup時用這個方法比較多,比如抽屜效果中:
[java] view plaincopy? ? ? 通過重寫這個方法來獲取手柄的View和要顯示內容的View。
5.2 onMeasure(int, int)
? ? ? ?測量這個View的高和寬。通過調用這個方法來設置View的測量后的高和寬,其最終調用的方法是:
[java] view plaincopy? ? ? ?可見其最終是將高和寬保存在mMeasuredWidth、mMeasuredHeight這兩個參數中。
? ? ? ?其實調用onMeasure(int, int)的方法的不是系統,而是
? ? ? ? ? ?public final voidmeasure(int widthMeasureSpec, int heightMeasureSpec)
? ? ? ?這個才是系統回調的方法,然后通過這個方法調用onMeasure(int, int)方法,個人感覺這種設計就是把系統方法和用戶可以重寫的方法分離開,這樣避免一些不必要的錯誤。
? ? ? ?在這個方法中主要是用來初始化各個子View的布局參數,我們來看看抽屜中的實現:
[java] view plaincopy? ? ? ?剛才我們已經獲取到mHandle和mContent的引用,因為onFinishInflate()方法調用在onMeasure(int, int)方法之前,所以這個不會出現nullPoint。我們可以看到在這個方法中主要就是為mHandle和mContent指定了布局參數。這里用到了MeasureSpec。
5.3 onLayout(boolean, int, int,int, int)
? ? ? ?onLayout是用來指定各個子View的位置,這個方法和上面方法類似,也不是真正的系統回調函數,真正的回調函數是Layout。這個方法的使用主要在ViewGroup中。這里不再詳述。我們在ViewGroup講解時再去了解這個方法。
5.4 onSizeChanged(int, int, int,int)
? ? ? ?這個是當View的大小改變時調用,這個也不再詳述,基本上用的也比較少。
5.5 onDraw(android.graphics.Canvas)
? ? ? ?這個方法相信大家都不會陌生了,在我以前的博客里也有這個方法的使用。當然那個比較入門,比較膚淺,呵呵。這里我們深入進去,類似于onMeasure(int, int),其實這個方法是由draw(Canvas)方法調用的。在這個方法中有一個對這個方法的描述:
[java] view plaincopy? ? ? ?我們可以看到:
? ? ? ? ? ? ? ?首先是繪制背景
? ? ? ? ? ? ? ?其次如果需要準備層之間的陰影
? ? ? ? ? ? ? ?然后繪制內容(這個內容就是調用我們的onDraw方法)
? ? ? ? ? ? ? ?再繪制children(dispatchDraw(canvas);)這個方法的調用主要實現在ViewGroup中,和繼承ViewGroup的組件中。
? ? ? ? ? ? ? ?如果需要繪制層之間的陰影。
? ? ? ? ? ? ? ?繪制裝飾,也就是scrollbars。
? ? ? ?dispatchDraw(canvas);這也是一個重要的方法,用于繪制子組件用的。下面是抽屜中的實現方法。也比較簡單,大家自行閱讀下也就了解了。
[java] view plaincopy? ? ? ?好了,這個就是View里面的內容,關于事件監聽我們這里就不再詳細描述,自定義組件的話,在寫完深入ViewGroup中會有一個專門的專題,而ViewGroup中也會去深化View中一些東西。
總結
以上是生活随笔為你收集整理的深入理解Android中View的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 教你搞定Android自定义View
- 下一篇: Android - View绘图原理总结