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 之后,是被忽略的。