android viewTree and decorView

Android ViewTree and DecorView

<!-- .entry-meta -->

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.

The tree structure as seen in Eclipse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<? 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.

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.

猜你喜欢

转载自huangqinqin.iteye.com/blog/1779714