Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android的ViewTree和DecorView使用示例

Android的ViewTree和DecorView使用示例

編輯:Android開發實例

 圖形用戶界面(GUI)是Android應用程序開發不可或缺的一部分。其不僅能為用戶提供輸入,還能夠根據(用戶)執行的動作,提供相應的反饋。因此,作為開發人員,能夠理解UI(用戶界面)是如何創建以及跟新的,就顯得尤為重要。

ViewTree

View 和 ViewGroup 是Android UI的基本組件, 而ViewGroup作為容器,可以包含一組View, 並且ViewGroup其本身就是View的擴展。看源碼:

public abstract class ViewGroup extends View implements ViewParent, ViewManager{} 

 

而各種不同的Widgets 像TextView, Button 等等 也是View的擴展,只不過是放在各種Layout裡,比如LinearLayout, RelativeLayout。而Layout卻是ViewGroup的子類。所以說一個ViewTree只不過是各種Views和ViewGroups放在一個Layout裡組成的樹形結構。

有例子才有真相。通過Eclipse的Outline窗口,我們可以看下下面這個樹狀布局。

 XML Code:

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:id="@+id/RelativeLayout1" 
  4.     android:layout_width="fill_parent" 
  5.     android:layout_height="fill_parent" > 
  6.   
  7.     <View 
  8.         android:id="@+id/WhiteView" 
  9.         android:layout_width="200dp" 
  10.         android:layout_height="300dp" 
  11.         android:layout_marginLeft="20dp" 
  12.         android:background="#ffffff" /> 
  13.   
  14.     <TextView 
  15.         android:id="@+id/RedText" 
  16.         android:layout_width="fill_parent" 
  17.         android:layout_height="wrap_content" 
  18.         android:layout_centerInParent="true" 
  19.         android:text="@string/hello" 
  20.         android:textColor="#ff0000" /> 
  21.   
  22.     <LinearLayout 
  23.         android:layout_width="wrap_content" 
  24.         android:layout_height="wrap_content" 
  25.         android:layout_above="@+id/GrayView" 
  26.         android:layout_alignLeft="@+id/GrayView" 
  27.         android:layout_marginBottom="25dp" 
  28.         android:background="#0000ff" 
  29.         android:orientation="vertical" > 
  30.   
  31.         <TextView 
  32.             android:id="@+id/GreenText" 
  33.             android:layout_width="wrap_content" 
  34.             android:layout_height="wrap_content" 
  35.             android:text="TextView" 
  36.             android:textColor="#00ff00" 
  37.             android:textStyle="bold" /> 
  38.   
  39.         <Button 
  40.             android:id="@+id/Button1" 
  41.             android:layout_width="wrap_content" 
  42.             android:layout_height="wrap_content" 
  43.             android:text="Button in LinearLayout" /> 
  44.     </LinearLayout> 
  45.       
  46.     <View 
  47.         android:id="@+id/RedView" 
  48.         android:layout_width="100dp" 
  49.         android:layout_height="100dp" 
  50.         android:layout_alignParentRight="true" 
  51.         android:layout_above="@+id/GrayView" 
  52.         android:layout_marginRight="10dp" 
  53.         android:layout_marginBottom="-10dp" 
  54.         android:background="#ff0000" /> 
  55.       
  56.     <View 
  57.         android:id="@+id/GrayView" 
  58.         android:layout_width="200dp" 
  59.         android:layout_height="300dp" 
  60.         android:layout_alignParentBottom="true" 
  61.         android:layout_alignParentRight="true" 
  62.         android:layout_marginRight="20dp" 
  63.         android:background="#cccccc" /> 
  64.   
  65. </RelativeLayout> 

 

 

當我們在Activity裡,用setContentView()去設置這個view,然後運行,我們可以看到如下圖:

 

仔細觀察XML文件,以及頁面渲染的View,我們會發現:

1. ViewTree 是以一種自上而下的方式進行遍歷實現。

2. Parent總是最先繪制的,其實才是Children,並且仍然遵循自上而下的方式。

所以在我們的例子中,RelativeLayout是最先繪制,接著是其孩子WhiteView,RedText 等等,

直到最終GrayView繪制,並且我們會看到後繪制的覆蓋了部分先繪制的。

 

 

 

為了更方便觀察這些Views是怎麼繪制的,我們把手機屏幕看作下面的X,Y,Z的坐標系。屏幕的左上角作為[0,0,0],X軸向右,Y軸向下沿著屏幕的長度,Z軸延伸出屏幕。


 所以說,當我們遍歷Tree的時候,這些Views基本上就是沿著Z軸排放。這裡需要注意,當View有部分被遮擋時,Android就不會再繪制這被遮擋的部分。比如上圖,灰色遮擋部分紅色,Android繪圖機制就不會再繪制那部分紅色,所以我們看到的是直接遮擋,而不是顏色的混合。

現在我們知道了我們在XML裡定義的Views是如何繪制的了,但是這還不夠,我們可以借助一個非常有用的工具Heirarchyviewer去更深層細的觀察頁面布局。

Heirarchyviewer 在文件夾android-sdk/tools下,在命令行下找到這個文件夾,然後執行heirarchyviewer.bat 就可以了。

 

 

下圖是Hierarchy Viewer的截圖:

在Hierarchy Viewer裡,列代表樹的深度,而每一列裡行的數量則表示每一層的深度。從圖上我們能注意到RelativeLayout並不是Root級別的,而是id為content的FrameLayout的一個子元素。而實際山我們調用setContentView(View v)裡的View v 就是這個content視圖。

 現在注意下跟content同級的FrameLayout有個子TextView,實際上它既是Activity的titleBar。那麼我們刪除這個TitleBar之後,View Tree又會變成什麼樣子呢?

 

 

方法:在manifest文件,然後修改application的主題如下:

android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"

這樣再打開Hierarchy Viewer,我們就能看到下圖:

(注意:本人選用的Android是2.2的,要是用4.1的話,並不能得到下圖,中間還會多一個Id為action_menu_bar_stub的ViewStub)

 這時候我們看到content FrameLayout的父元素是PhoneWindow$DecorView。

DecorView

我們知道在Android中抽象類Window定義了最上層窗口的基本外觀以及基本行為,她的實例將會被加到WindowManager中,提供一些標准的UI策略,像Background,Titlebar,以及Default key processing等等,當然這些屬性是可以通過WindowManager.LayoutParams定制的。

而上面提到的PhoneWindow是Window抽象類的唯一實現,即android.policy.PhoneWindow。而DecorWindow是PhoneWindow的一個私有內部類,其實就是一個FrameLayout的擴展。

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {}

就是這個類構成了最上層應用程序視圖。根據我們在Manifest中設置的Theme或者在PhoneWindow設置的Flags,來確定DecorView的Layout。所以在我們的例子中,第一張中我們有個簡單的主題(在Manifest中)包含一個titlebar和contentview,於是PhoneWindow就生成了包含Title的LinearLayout,以及放置content的FrameLayout。而在第二張圖中,我們去掉了titlebar主題,所以她就只生成了包含FrameLayout的DecorView了。

結論

最後我們來總結下,當一個Activity被啟動的時候,這個視圖樹(View Tree)大體是如何創建的呢:

1. PhoneWindow根據Manifest的主題或者是特定的PhoneWindow設置去生成一個DevorView的布局,作為跟視圖(Root View)。

2. Activity調用setContentView()方法把用戶自定義的Layout XML文件作為內容視圖(Content View), 當然其內部是調用PhoneWindow的setContentView()方法。

3. 經過上兩步,UI視圖就已經形成了,那麼當UI每次被刷新的時候,View Tree就會像上面所說的那樣被Traverse。

 

原文地址:http://www.shubhayu.com/android/android-viewtree-and-decorview

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved