android 布局中经常会用到 <merge></merge> 标签,来优化 ui 布局。
具体如何优化,可以借助 android sdk 提供的 tools/hierarchyviewer 工具。
这个工具,并不是万能的,你需要自己去根据实际情况分析和优化自己的布局。
该工具的使用可以查阅资料,这里不赘述。
关于 <merge></merge> 使用,推荐一篇文章,简单明了
http://www.bangchui.org/simple/?t17479.html
其实这里面还有其他标签的介绍如 include、viewstub 等。
另外,http://developer.android.com/training/improving-layouts/reusing-layouts.html
也介绍了 merge 以及merge 的好处(可以用来优化布局)。
这里总结一下 merge 注意事项
1. merge 只可以是一个布局文件中的根节点,不可以有父节点。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ssb"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<merge>
<!-- 省略 -->
</merge>
</LinearLayout>
这个就是错误的,错误报告内容如下:
2. merge 可以包含 include 标签,反之不行
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
<include
android:id="@+id/newone"layout="@layout/share">
</include>
<include
android:id="@+id/newtwo"layout="@layout/share">
</include>
</merge>
上面的用法是正确的。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ssb"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include>
<merge>
<!-- 省略 -->
</merge>
</include>
</LinearLayout>
这种用法是错误的(也是类似 1 的错误)。
3. include 可以间接包含 merge
mergedemo.xml 文件
<?xml version="1.0" encoding="utf-8"?>
<merge 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:contentDescription="@null"
android:scaleType="centerInside" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:background="@drawable/sb_msg_count"
android:gravity="center"
android:textColor="@android:color/white" />
</merge>
main.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="wrap_content"
android:orientation="vertical">
<include layout="@layout/mergedemo" />
</LinearLayout>
注意这种情况下,include 进来的 xml 文件,merge 就会被忽略,没有任何作用。
也就是说,main.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="wrap_content"
android:orientation="vertical" >
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:contentDescription="@null"
android:scaleType="centerInside" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:gravity="center"
android:textColor="@android:color/white" />
</LinearLayout>
这一点要注意!
4. 使用 inflate 加载 merge 布局文件
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ssb"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
mergedemo.xml
<?xml version="1.0" encoding="utf-8"?>
<merge 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:contentDescription="@null"
android:scaleType="centerInside" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:gravity="center"
android:textColor="@android:color/white" />
</merge>
activity.java
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 找到父节点
LinearLayout superlayout = (LinearLayout) findViewById(R.id.ssb);
// 实例化 LayoutInflater
LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
// inflate
View view = inflater.inflate(R.layout.mergedemo, superlayout, true);
// 显示
setContentView(superlayout);
}
这里需要注意几个问题
(a). inflater.inflate(R.layout.mergedemo, superlayout, true);
必须指定 superlayout 和 true,否则报错。
(b). 不需要再次 addview
// 找到父节点
LinearLayout superlayout = (LinearLayout) findViewById(R.id.ssb);
// 实例化 LayoutInflater
LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
// inflate
View view = inflater.inflate(R.layout.mergedemo, superlayout, true);
superlayout.addView(view);
// 显示
setContentView(superlayout);
代码 superlayout.addView(view); 是多余的。
具体可以查看 LayoutInflater.java 源码
5. merge 并不是一定可以取代 FrameLayout 标签。
这个需要视具体情况而定,merge 被 include 之后,是被忽略的。