我读过Romain Guy关于<merge />标签的帖子,但我仍然不明白它有什么用。它是<Frame />标签的一种替代,还是像这样使用:

<merge xmlns:android="....">
<LinearLayout ...>
    .
    .
    .
</LinearLayout>
</merge>

然后<include />代码在另一个文件?


当前回答

基于android官方文档,你必须使用合并在FrameLayout的地方,如果它不提供任何填充或空白等。

引用:

合并根帧-如果一个FrameLayout是一个布局的根 不提供背景或填充等,它可以用合并代替 标签,这稍微更有效。

文档链接

其他回答

为了更深入地了解正在发生的事情,我创建了以下示例。看一下activity_main.xml和content_profile.xml文件。

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/content_profile" />

</LinearLayout>

content_profile.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Howdy" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hi there" />

</LinearLayout>

在这里,整个布局文件膨胀后是这样的。

<LinearLayout>
    <LinearLayout>
        <TextView />
        <TextView />
    </LinearLayout>
</LinearLayout>

在父LinearLayout中有一个LinearLayout,它没有任何用途,是多余的。通过布局检查器工具查看布局清楚地解释了这一点。

content_profile.xml在更新代码后使用合并而不是像LinearLayout这样的ViewGroup。

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Howdy" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hi there" />

</merge>

现在我们的布局是这样的

<LinearLayout>
    <TextView />
    <TextView />
</LinearLayout>

这里我们看到多余的LinearLayout ViewGroup被删除了。现在布局检查器工具给出了如下的布局层次结构。

当你的父布局可以定位你的子布局时,总是尝试使用归并,或者更准确地说,当你知道层次结构中会有多余的视图组时,使用归并。

基于android官方文档,你必须使用合并在FrameLayout的地方,如果它不提供任何填充或空白等。

引用:

合并根帧-如果一个FrameLayout是一个布局的根 不提供背景或填充等,它可以用合并代替 标签,这稍微更有效。

文档链接

<merge/>是有用的,因为它可以摆脱不需要的viewgroup,即布局只是用来包装其他视图,本身没有任何用途。

例如,如果你要<include/>一个布局从另一个文件没有使用合并,这两个文件可能看起来像这样:

layout1.xml:

<FrameLayout>
   <include layout="@layout/layout2"/>
</FrameLayout>

layout2.xml:

<FrameLayout>
   <TextView />
   <TextView />
</FrameLayout>

这在功能上等同于这个单一的布局:

<FrameLayout>
   <FrameLayout>
      <TextView />
      <TextView />
   </FrameLayout>
</FrameLayout>

layout2.xml中的FrameLayout可能没有用处。<merge/>帮助摆脱它。下面是使用merge (layout1.xml没有改变)的样子:

layout2.xml:

<merge>
   <TextView />
   <TextView />
</merge>

这在功能上等同于下面的布局:

<FrameLayout>
   <TextView />
   <TextView />
</FrameLayout>

但是由于您使用的是<include/>,您可以在其他地方重用该布局。它不需要只用来替换framamelayouts -你可以用它来替换任何没有为视图的外观/行为添加有用内容的布局。

blazeroni已经说得很清楚了,我只想补充几点。

<merge>用于优化布局。它用于减少不必要的嵌套。 当包含<merge>标签的布局被添加到另一个布局中时,<merge>节点将被移除,它的子视图将直接添加到新的父视图中。

使用merge的另一个原因是在ListViews或gridview中使用自定义视图组。您可以使用自定义视图,而不是在列表适配器中使用viewHolder模式。自定义视图将膨胀根为merge标记的xml。 适配器代码:

public class GridViewAdapter extends BaseAdapter {
     // ... typical Adapter class methods
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
        WallpaperView wallpaperView;
        if (convertView == null)
           wallpaperView = new WallpaperView(activity);
        else
            wallpaperView = (WallpaperView) convertView;

        wallpaperView.loadWallpaper(wallpapers.get(position), imageWidth);
        return wallpaperView;
    }
}

下面是自定义视图组:

public class WallpaperView extends RelativeLayout {

    public WallpaperView(Context context) {
        super(context);
        init(context);
    }
    // ... typical constructors

    private void init(Context context) {
        View.inflate(context, R.layout.wallpaper_item, this);
        imageLoader = AppController.getInstance().getImageLoader();
        imagePlaceHolder = (ImageView) findViewById(R.id.imgLoader2);
        thumbnail = (NetworkImageView) findViewById(R.id.thumbnail2);
        thumbnail.setScaleType(ImageView.ScaleType.CENTER_CROP);
    }

    public void loadWallpaper(Wallpaper wallpaper, int imageWidth) {
        // ...some logic that sets the views
    }
}

这是XML文件:

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <ImageView
        android:id="@+id/imgLoader"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_centerInParent="true"
        android:src="@drawable/ico_loader" />

    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/thumbnail"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</merge>