天天看點

view viewGroup

2.1.0 View及ViewGroup類關系

Android View和ViewGroup從組成架構上看,似乎ViewGroup在View之上,View需要繼承ViewGroup,但實際上不是這樣的。View是基類,ViewGroup是它的子類。這就證明了一點,View代表了使用者界面元件的一塊可繪制的空間塊。每一個View在螢幕上占據一個長方形區域。在這個區域内,這個VIEW對象負責圖形繪制和事件處理。View是小控件widgets和ViewGroup的父類。ViewGroup又是Layout的基類。

view viewGroup
view viewGroup

從上面兩圖的對比中,可以看出,實際上ViewGroup是View的子類,是以,View的行為特征ViewGroup也具備,但同時因為ViewGroup是Layout的祖先,是以具備了其它一些特點,View所未具有的。通常建立一個View,不論是通過XML還是通過代碼建立。對任何一個View及這個View的子類Widget,需要關注如下幾個方面:

【1】設定屬性,如長、寬、着色等。這些屬性的設定通常可以用代碼實作,也可以用XML檔案。并用這些屬性在運作時候也可以通常方法進行修改。

ID 屬性,Android對每個UI元素的ID名稱要求唯一,但也不絕對。同時在不同的Layout中是可以相同的元素名稱的。給一個UI元素指定ID,有一個好處就是可以在代碼中找得到。

view viewGroup

Tags,同ID不同,這個不用來搜尋View,類似于對View的一些描述性資料儲存。

Animation,對任何一個View,可以使用動畫對象進行操作。注意,如果View有子的話,子同樣具備這個animation功能

Position, Size, padding and margins,對任一個View來說,表達這個View通常是寬和高。也可以設定padding和margins。不是所有的View都設定margins。

view viewGroup

Orientatiion,對ViewGroup的子類Layout來說,設定Orienatation,可用來決定子類的位置

FillModel,出現這種情況主要是預設情況,某些元素不能完全占滿父區域的空間,這時除非子VIEW已經設定具體和DPI,否則話需要告訴父控件,你所選擇填充空間方式,如Fill-parent或者Wrap-content等。

Gravity,Gravity與Orientation是不同,Gravaity與Word文檔中左對齊,右對齊類似。預設是左上對齊。

Weight,這個在兩個控制同時配置設定剩餘空間,需要設定layout-weight決定兩者誰的占比。

【2】請求焦點,可以通過函數實作焦點轉換。不同的焦點可以實作不同的背景變換等功能。焦點在Android裡分為幾種情況,一種是可以擷取焦點,另外一種是不能擷取焦點,第三種是可擷取焦點,但目前正取觸摸狀态下。

【3】設定事件監聽者,所有的View都會在本身發生變化将自身的資訊廣播出去。比喻點選、焦點失去得到等。通常一個事件來到,Android會将事件傳遞到相應的View,然後View将事件傳遞到相應的Listeners。這時View需要擷取焦點,如果需要重新繪制View的話,需要調用invalidate(0或者reqeustLayout重新繪制整個界面。

【4】設定顯示與隐藏,還可以對其内容設定scrolling。

2.1.1 View、Window、Activity、Dispay之間的關系

這些都是組成Android 系統顯示的關鍵元素。我們首先來了解Dispay。Dispay代表了硬體顯示螢幕資訊。

view viewGroup

通過這些函數可以了解一個螢幕的寬、高及分辨率還有是橫屏還堅屏等一些基本情況,透過這些函數,我們開發應用時可以友善的得到目前安裝我這個應用的螢幕的大小,以便調整應用使使用者得到更好的使用者體驗。接下來我們看其它三者之間的關系,我想大家雖然看了前面的View的介紹和SDK中關系UI的基本介紹之後還是對Android圖形視窗十分困惑,看API也是,有WindowMangaer接口和Window類,但是在說明文檔中,并未提到如何用這些。但實際上這裡面要去看到Android核心,Android核心底層GDI是SKIA,同chrome是一樣的GDI,但是GUI是不一樣的。這裡面Android實作的是C/S模式。如下圖所示

view viewGroup

從上圖,我們可以理出大緻的顯示過程如下:

【1】ActivityManagerService建立Activity線程,激活一個activity

【2】系統調用Instrumentation.newActivity建立一個activity

【3】Activity建立後,attach到一個新建立的phonewindow中。這樣Activity擷取一個唯一的WindowManager服務的執行個體

【4】Activity建立過程中使用setcontentView設定用使用者UI,這些VIEW被加入到PhoneWindow的ContentParent中。

【5】Activity線程繼續執行,當執行到Activity.makeVisible是将根view DecoView加入到WindowManger中,WindowManger實全會為每個DecoView建立對應的ViewRoot

【6】每個ViewRoot擁有一個Surface,每個Surface将會調用底層庫建立圖形繪制的記憶體空間。這個底層庫就是SurfaceFlinger。SurfaceFlinger同時也負責将個View繪制的圖形合到一塊(按照Z軸)顯示到使用者螢幕。

【7】如果使用者直接在Canvas上繪制,實際上它直接操作Surface。但對每個View的變更,它是要通知到ViewRoot,然後ViewRoot擷取Canvas。如果繪制完成,surfaceFlinger得到通知,合并Surface成一個Surface到裝置螢幕。

從上面的圖形輸出過程分析,我們可以知道真正顯示圖形的實際上跟Activity沒有關系,完全由WindowManager來決定。WindowManager是一個系統服務,是以可以直接調用這個服務來建立界面,并且更絕的是Dialog、Menu也是有WindowManager來管理的。另外一個我們也可以看到,最底層都是Surface來,是以,常見開發遊戲的人都推薦你使用SurfaceView來建立界面。

繼續閱讀