爱悠闲 > UI 效果(9):merge 的点点滴滴

UI 效果(9):merge 的点点滴滴

分类: Android View/UI  |  标签: android,Android,include,layout,merge  |  作者: veryitman 相关  |  发布日期 : 2012-12-11  |  热度 : 908°

android 布局中经常会用到 <merge></merge> 标签,来优化 ui 布局。

具体如何优化,可以借助 android sdk 提供的 tools/hierarchyviewer 工具。


这个工具,并不是万能的,你需要自己去根据实际情况分析和优化自己的布局。

该工具的使用可以查阅资料,这里不赘述。


关于  <merge></merge> 使用,推荐一篇文章,简单明了

链接地址


其实这里面还有其他标签的介绍如 include、viewstub 等。


另外,链接地址

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