The Graphical User Interface forms an integral part of the Android application development. The UI not only acts as a mode of input for the user but also as a mode of feedback from the application based upon an action performed. It is therefore very important that a developer understands how the UI is created and updated.

ViewTree

The basic components of the visual UI is the View and a container called ViewGroup which contains a collection of Views. The ViewGroup itself is an extension of a View. The different widgets like the TextView, Button, etc are nothing but extensions of View which are all arranged within layouts, viz. LinearLayout, RelativeLayout. The layouts are nothing but sub classes of ViewGroup. A ViewTree is nothing but the tree structure that is formed as a collection of these views and viewgroups in a layout.

Let’s start with an example. Here you can see that a number of Views and a LinearLayout are all contained within a RelativeLayout which acts as the parent ViewGroup. All of these come together to form the ViewTree.

android 的View Tree和 DecorView(Android ViewTree and DecorView)_第1张图片

The tree structure as seen in Eclipse

<?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>

When you set the view in your activity using setContentView() and run the program, you’ll see something like this.

If you see the xml file and the way each of the views have been drawn, you’ll observe the following.

  1. The ViewTree that is formed is traversed in a top-down fashion.
  2. The parent is always drawn first and then the children, again in a top-down fashion.

So in our example, the RelativeLayout Layout is first drawn, followed by its children WhiteView, RedText and so on, till finally GrayView is drawn obscuring the Views drawn before.

To visualize, how all the views are being drawn, think of the screen as a coordinate system consisting of X, Y and Z axes and the top-left of the screen as [0,0,0]. X extends to the right, while positive Y extends along the length of the screen. Z extends out of the screen. However do not confuse this system with the coordinate system of the Sensors of the phone.

The View Layout structure and their z-order

So the Views are basically placed along the positive Z axis as we move down the tree. Note that the Android drawing mechanism takes care that it does not draw parts of Views which are hidden by Views placed with greater z-values.

Now that we know how the Views defined by us in the xml are drawn, let us see if this all that there is in the View Tree. For this, we need the help of a tool known as the “heirarchyviewer” in the android installation folder under android-sdk/tools. Before we can use this tool, first run the program in the emulator or the device. Use the commandline to navigate to the folder and start the heirarchyviewer.bat file.

Shown below is the snapshot of the hierarchy viewer.

In the hierarchy viewer, the columns represent the depth of the tree while the number of rows in each column represents the breadth at each level. So you will notice that our RelativeLayout is not really at the root level but is in fact a child of a FrameLayout called “content”. The call to the setContentView(View v) basically sets the View v as the content view.

TreeView heirarchy of an Activity with a TitleBar

Now notice the column containing the FrameLayout “content”. It has a sibling which is another FrameLayout containing a TextView. This is nothing but the Title Bar of the Activity. Let’s see how the View Tree changes if we the titlebar is removed. Go to the manifest file and add the following line to thetag

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

On running the hierarchy viewer, you will notice that the structure has changed. The content view now has just the “content” FrameLayout whose parent is the PhoneWindow$DecorView.

android 的View Tree和 DecorView(Android ViewTree and DecorView)_第2张图片

TreeView of the Activity without the TitleBar

Let us take a look at the PhoneWindow and the DecorView.

DecorView

PhoneWindow is the only implementation of the abstract “Window” class which provides the policies defining the look and feel of a window. It forms the top-level window which together with the WindowManager helps in setting the background, title area (either with TitleBar, ActionBar or a user specific custom title bar) and default key processing. The overall window properties can be customized using the WindowManager.LayoutParams.

The DecorView is a private class of the PhoneWindow which is nothing but an extension of FrameLayout. This is the class which forms the top-level application view. Based upon the settings provided in the Android Manifest regarding the themes or the flags set in the PhoneWindow on what type of a window we need to create, the layout of the DecorView is created. So for our example, in the first case, we had a simple theme containing containing a title bar and the contentview. The Phone Window generates a layout that consists of a linearlayout with the title and a framelayout where the contentview can be set. In the second case, we specified that we did not need a titlebar and hence it created the decorview with just the framelayout where the contentview can be set.

Conclusion

So here’s a brief of how the View Tree is generated when a Activity is started,

  1. The PhoneWindow generates a layout for the DecorView which forms the root view based upon the theme provided in the manifest file or otherwise specified using the Window interface.
  2. The activity’s setContentView() is used to set the layout xml as the content view. This internally calls the PhoneWindow’s setContentView().
  3. Now everytime the UI is refreshed the View Tree is traversed as mentioned earlier.

Note:If you plan to use a custom title bar using FEATURE_CUSTOM_TITLE, note that calling setContentView() for the first time or getDecorView() fixes your decorview and you can no longer change many window characteristics. Keep this in mind while designing.

android 的View Tree和 DecorView(Android ViewTree and DecorView)_第3张图片

一、DecorView为整个Window界面的最顶层View。

二、DecorView只有一个子元素为LinearLayout。代表整个Window界面,包含通知栏,标题栏,内容显示栏三块区域。

三、LinearLayout里有两个FrameLayout子元素。

(20)为标题栏显示界面。只有一个TextView显示应用的名称。也可以自定义标题栏,载入后的自定义标题栏View将加入FrameLayout中。

(21)为内容栏显示界面。就是setContentView()方法载入的布局界面,加入其中。

工具查看:

1.

下图为SDK中tools文件夹下hierarchyviewer bat 查看ViewTree的结果:

(此时未替换标题栏)

android 的View Tree和 DecorView(Android ViewTree and DecorView)_第4张图片

2.替换标题栏后ViewTree的变化:

android 的View Tree和 DecorView(Android ViewTree and DecorView)_第5张图片

绿色区域发生了变化,改变为了载入的title.xml文件的布局。

title.xml内容为:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon2"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/title_tv"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:text="@string/app_name"
/>
</LinearLayout>

通知栏绘制在1号LinearLayout中,还是绘制在DecorView中还有待探究。

-----------------

ApiDemo中app包下CustomTitle中自定义TitleBar代码段

requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.custom_title);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_1);

载入自定义titleBar后如何查找其中元素呢,其实还是findViewById就可以了,因为载入的自定义布局已经在DecorView树中了

而findViewById是怎么回事呢。

activity中findViewById源码

public View findViewById(int id) {
return getWindow().findViewById(id);
}

调用了getWindow().findViewById,getWindow返回的是Window点入查看window中源码

public View findViewById(int id) {
return getDecorView().findViewById(id);
}

所以最终是从DecorView最顶层开始搜索的。


更多相关文章

  1. 改变ProgressBar的图片
  2. android常用图片特效处理
  3. 一张图片覆盖在另一个图片上
  4. Android帧布局-实现渐变效果
  5. Android布局属性大全
  6. Android布局的一些属性值
  7. Android布局详解(一)

随机推荐

  1. Android--ListView滑动时出现黑屏解决方
  2. An exisiting Android(安卓)SDK was dete
  3. 网络---《第一行代码Android》笔记
  4. android 常用代码备份
  5. Android+Junit单元测试1
  6. android 实现类似Iphone底部消息数量提示
  7. android JNI cocos2dx调用对话框
  8. Android 修改项目名称
  9. android AnimationDrawable类实现动画效
  10. 通话距离感应实现源码