西西軟件下載最安全的下載網(wǎng)站、值得信賴的軟件下載站!

首頁(yè)編程開發(fā)Android → Android圖形用戶界面開發(fā)之ViewTree和DecorView詳細(xì)介紹

Android圖形用戶界面開發(fā)之ViewTree和DecorView詳細(xì)介紹

相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來源:西西整理時(shí)間:2013/1/4 0:23:10字體大。A-A+

作者:西西點(diǎn)擊:19次評(píng)論:0次標(biāo)簽: 圖形用戶界面

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

ViewTree

View 和 ViewGroup 是Android UI的基本組件, 而ViewGroup作為容器,可以包含一組View, 并且ViewGroup其本身就是View的擴(kuò)展?丛创a:

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

而各種不同的Widgets 像TextView, Button 等等 也是View的擴(kuò)展,只不過是放在各種Layout里,比如LinearLayout, RelativeLayout。而Layout卻是ViewGroup的子類。所以說一個(gè)ViewTree只不過是各種Views和ViewGrouPS放在一個(gè)Layout里組成的樹形結(jié)構(gòu)。

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

 XML Code:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/RelativeLayout1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
 
    <View
        android:id="@+id/WhiteView"
        android:layout_width="200dp"
        android:layout_height="300dp"
        android:layout_marginLeft="20dp"
        android:background="#ffffff" />
 
    <TextView
        android:id="@+id/RedText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/hello"
        android:textColor="#ff0000" />
 
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/GrayView"
        android:layout_alignLeft="@+id/GrayView"
        android:layout_marginBottom="25dp"
        android:background="#0000ff"
        android:orientation="vertical" >
 
        <TextView
            android:id="@+id/GreenText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView"
            android:textColor="#00ff00"
            android:textStyle="bold" />
 
        <Button
            android:id="@+id/Button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button in LinearLayout" />
    </LinearLayout>
     
    <View
        android:id="@+id/RedView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentRight="true"
        android:layout_above="@+id/GrayView"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="-10dp"
        android:background="#ff0000" />
     
    <View
        android:id="@+id/GrayView"
        android:layout_width="200dp"
        android:layout_height="300dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginRight="20dp"
        android:background="#cccccc" />
 
</RelativeLayout>

當(dāng)我們?cè)贏ctivity里,用setContentView()去設(shè)置這個(gè)view,然后運(yùn)行,我們可以看到如下圖:

仔細(xì)觀察XML文件,以及頁(yè)面渲染的View,我們會(huì)發(fā)現(xiàn):

1. ViewTree 是以一種自上而下的方式進(jìn)行遍歷實(shí)現(xiàn)。

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

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

直到最終GrayView繪制,并且我們會(huì)看到后繪制的覆蓋了部分先繪制的。

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


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

現(xiàn)在我們知道了我們?cè)赬ML里定義的Views是如何繪制的了,但是這還不夠,我們可以借助一個(gè)非常有用的工具Heirarchyviewer去更深層細(xì)的觀察頁(yè)面布局。

Heirarchyviewer 在文件夾android-sdk/tools下,在命令行下找到這個(gè)文件夾,然后執(zhí)行heirarchyviewer.bat 就可以了。

下圖是Hierarchy Viewer的截圖:

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

 現(xiàn)在注意下跟content同級(jí)的FrameLayout有個(gè)子TextView,實(shí)際上它既是Activity的titleBar。那么我們刪除這個(gè)TitleBar之后,View Tree又會(huì)變成什么樣子呢?

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

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

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

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

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

DecorView

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

而上面提到的PhoneWindow是Window抽象類的唯一實(shí)現(xiàn),即android.policy.PhoneWindow。而DecorWindow是PhoneWindow的一個(gè)私有內(nèi)部類,其實(shí)就是一個(gè)FrameLayout的擴(kuò)展。

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {}

就是這個(gè)類構(gòu)成了最上層應(yīng)用程序視圖。根據(jù)我們?cè)贛anifest中設(shè)置的Theme或者在PhoneWindow設(shè)置的Flags,來確定DecorView的Layout。所以在我們的例子中,第一張中我們有個(gè)簡(jiǎn)單的主題(在Manifest中)包含一個(gè)titlebar和contentview,于是PhoneWindow就生成了包含Title的LinearLayout,以及放置content的FrameLayout。而在第二張圖中,我們?nèi)サ袅藅itlebar主題,所以她就只生成了包含F(xiàn)rameLayout的DecorView了。

結(jié)論

最后我們來總結(jié)下,當(dāng)一個(gè)Activity被啟動(dòng)的時(shí)候,這個(gè)視圖樹(View Tree)大體是如何創(chuàng)建的呢:

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

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

3. 經(jīng)過上兩步,UI視圖就已經(jīng)形成了,那么當(dāng)UI每次被刷新的時(shí)候,View Tree就會(huì)像上面所說的那樣被Traverse。

    相關(guān)評(píng)論

    閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無(wú)聊無(wú)聊

    熱門評(píng)論

    最新評(píng)論

    發(fā)表評(píng)論 查看所有評(píng)論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過審核才能顯示)