編輯:Android開發實例
圖形用戶界面(GUI)是Android應用程序開發不可或缺的一部分。其不僅能為用戶提供輸入,還能夠根據(用戶)執行的動作,提供相應的反饋。因此,作為開發人員,能夠理解UI(用戶界面)是如何創建以及跟新的,就顯得尤為重要。
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:
- <?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>
當我們在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。
我們知道在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
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩
1、用於沒有一點提示的情況:依次打開eclipse上面的windows ——preferences ——java ——editor —— content assi
在Andoird使用Android自帶的那些組件,像SlidingDrawer和DrawerLayout都是抽屜效果的菜單,但是在項目很多要實現的功能都收到And
在Android中使用ImageView顯示圖片的時候發現圖片顯示不正,方向偏了或者倒過來了。 解決這個問題很自然想到的分兩步走: 1、自動識別圖像方向,計算旋轉