Hierarchy Viewer 帮你分析应用程序UI布局
Hierarchy Viewer在android的工具文件夹里: /android/tools/hierarchyviewer.bat
1.启动 模拟器。
2.到/android/tools/目录下,双击可以启动hierarchyviewerbat文件,打开一个图形界面。
3.点击 load View hierarchy按钮,就可以捕获模拟器当前activity的画面布局信息。
4.hierarchy可以通过树形结构展示布局形式。
5.双击树节点可以展示单独的UI部分。
6.当模拟器activity画面变更后,点击refresh可以加载新的页面布局信息。
通过Hierarchy Viewer你就可以学习别人优秀的布局方式,
同时也更能更深入更全面更整体的把握xml布局文件。
体会UI和代码(java code)以及资源(res)的相互分离
1.使用<include /> 标签来重用layout代码
如果在一个项目中需要用到相同的布局设计,可以通过<include /> 标签来重用layout代码,该标签在android开发文档中没有相关的介绍。在android主屏程序中 用到了这个标签:
这样可以多次引用一个布局片段而不用重复的复制、粘贴。通过include标签也可以覆写一些属性的值,例如上面的示例就覆写了引用的layout中的id值。下面是另外一个示例:
- <include android:layout_width="fill_parent"layout="@layout/image_holder" />
- <include android:layout_width="256dip" layout="@layout/image_holder" />
2.使用<merge /> 标签来减少视图层级结构 在Android layout文件中需要一个顶级容器来容纳其他的组件,而不能直接放置多个组件,例如如下的代码:
- <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <ImageView
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:scaleType="center"
- android:src="@drawable/golden_gate" />
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Golden Gate" />
- </FrameLayout>
单独将<merge />标签做个介绍,是因为它在优化UI结构时起到很重要的作用。目的是通过删减多余或者额外的层级,从而优化整个Android Layout的结构。
3.将通过一个例子来了解这个标签实际所产生的作用,这样可以更直观的了解<merge/>的用法。
建立一个简单的Layout,其中包含两个Views元素:ImageView和TextView 默认状态下我们将这两个元素放在FrameLayout中。其效果是在主视图中全屏显示一张图片,之后将标题显示在图片上,并位于视图的下方。以下是xml代码:
应用上边的Layout运行的视图为:
启动 tools> hierarchyviewer.bat工具查看当前UI结构视图:
我们可以很明显的看到由红色线框所包含的结构出现了两个framelayout节点,很明显这两个完全意义相同的节点造成了资源浪费(这里可以提醒大家在开发工程中可以习惯性的通过hierarchyViewer查看当前UI资源的分配情况),那么如何才能解决这种问题呢(就当前例子是如何去掉多余的frameLayout节点)?这时候就要用到<merge />标签来处理类似的问题了。我们将上边xml代码中的framLayout替换成merge:
运行程序后在Emulator中显示的效果是一样的,可是通过hierarchyviewer查看的UI结构是有变化的,当初多余的FrameLayout节点被合并在一起了,或者可以理解为将merge标签中的子集直接加到Activity的FrameLayout跟节点下(这里需要提醒大家注意:所有的Activity视图的根节点都是frameLayout)。如果你所创建的Layout并不是用framLayout作为根节点(而是应用LinerLayout等定义root标签),就不能应用上边的例子通过merge来优化UI结构。
4.除了上边的例子外,meger还有另外一个用法
当应用Include或者ViewStub标签从外部导入xml结构时,可以将被导入的xml用merge作为根节点表示,这样当被嵌入父级结构中后可以很好的将它所包含的子集融合到父级结构中,而不会出现冗余的节点。
另外有两点需要特别注意:
使用<include /> 标签来重用layout代码
如果在一个项目中需要用到相同的布局设计,可以通过<include /> 标签来重用layout代码,该标签在android开发文档中没有相关的介绍。在android主屏程序中 用到了这个标签:
<com.android.launcher.Workspace android:id="@+id/workspace" android:layout_width="fill_parent" android:layout_height="fill_parent" launcher:defaultScreen="1"> <include android:id="@+id/cell1" layout="@layout/workspace_screen" /> <include android:id="@+id/cell2" layout="@layout/workspace_screen" /> <include android:id="@+id/cell3" layout="@layout/workspace_screen" /> </com.android.launcher.Workspace>
这样可以多次引用一个布局片段而不用重复的复制、粘贴。通过include标签也可以覆写一些属性的值,例如上面的示例就覆写了引用的layout中的id值。下面是另外一个示例:
<include android:layout_width="fill_parent" layout="@layout/image_holder" /> <include android:layout_width="256dip" layout="@layout/image_holder" /> 使用<merge /> 标签来减少视图层级结构 在Android layout文件中需要一个顶级容器来容纳其他的组件,而不能直接放置多个组件,例如如下的代码 :
< FrameLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent" >
< ImageView
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:scaleType = "center"
android:src = "@drawable/golden_gate" />
< TextView
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "Golden Gate" />
</ FrameLayout >
上面的代码显示一个图片,然后在图片上方显示一个title, 结果如下图: android activity的默认布局为FrameLayout,这样上面的布局代码就有2层FrameLayout ,通过HierarchyViewer 工具看到的结构如下: 如果能在layout文件中把FrameLayout 声明去掉就可以进一步优化布局代码了。 但是由于布局代码需要外层容器容纳,如果 直接删除FrameLayout 则该文件就不是合法的布局文件。这种情况下就可以使用<merge /> 标签了。 修改为如下代码就可以消除多余的FrameLayout了:
< merge xmlns:android = "http://schemas.android.com/apk/res/android" >
< ImageView
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:scaleType = "center"
android:src = "@drawable/golden_gate" />
< TextView
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "Golden Gate" />
</ merge >
通过HierarchyViewer工具看到的结构如下: merge也有一些使用限制: 只能用于xml layout文件的根元素;在代码中inflate一个以merge为根元素的 布局文件时候,你需要指定一个ViewGroup 作为其容器,并且要设置attachToRoot 为true,详细信息参考 inflate()函数doc。 上面示例项目代码: http://progx.org/users/Gfx/android/MergeLayout.zip