<merge />
标签上的帖子,但我仍然不明白它的用处。是对<Frame />
标签的某种替换,还是这样使用:<merge xmlns:android="....">
<LinearLayout ...>
.
.
.
</LinearLayout>
</merge>
然后
<include />
另一个文件中的代码?#1 楼
<merge/>
很有用,因为它可以摆脱不需要的ViewGroup,即仅用于包装其他视图且本身无用的布局。例如,如果您要从另一个文件中进行布局而不使用<include/>
使用合并,这两个文件可能看起来像这样:layout1.xml:
<FrameLayout>
<include layout="@layout/layout2"/>
</FrameLayout>
layout2.xml:
<在功能上等效于此单个布局的
:
<FrameLayout>
<TextView />
<TextView />
</FrameLayout>
layout2.xml中的FrameLayout可能没有用。
<merge/>
帮助摆脱它。这是使用合并的样子(layout1.xml不变):layout2.xml:
<FrameLayout>
<FrameLayout>
<TextView />
<TextView />
</FrameLayout>
</FrameLayout>
这在功能上是等效的到此布局:
<merge>
<TextView />
<TextView />
</merge>
,但是由于您使用的是
<include/>
,因此您可以在其他地方重用该布局。它不必用于仅替换FrameLayouts -您可以使用它来替换不会为视图的外观/行为添加任何有用内容的任何布局。#2 楼
include标签<include>
标签可让您将布局分为多个文件:有助于处理复杂或过长的用户界面。假设您使用以下方法拆分复杂的布局两个包含文件如下:
top_level_activity.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- First include file -->
<include layout="@layout/include1.xml" />
<!-- Second include file -->
<include layout="@layout/include2.xml" />
</LinearLayout>
然后您需要编写
include1.xml
和include2.xml
。请记住,包含文件中的xml只是在渲染时转储到您的
top_level_activity
布局中(非常类似于C的#INCLUDE
宏)。包含文件是纯文本文件简布局xml。
include1.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textView1"
android:text="First include"
android:textAppearance="?android:attr/textAppearanceMedium"/>
...和include2.xml:
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/button1"
android:text="Button" />
看到了吗?没有什么花哨。
请注意,您仍然必须使用
xmlns:android="http://schemas.android.com/apk/res/android
声明android名称空间。,因此top_level_activity.xml的呈现版本为:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- First include file -->
<TextView
android:id="@+id/textView1"
android:text="First include"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<!-- Second include file -->
<Button
android:id="@+id/button1"
android:text="Button" />
</LinearLayout>
在您的Java代码中,所有这些都是透明的:活动类中的
findViewById(R.id.textView1)
返回正确的窗口小部件(即使该窗口小部件是在不同于活动布局的xml文件中声明的)。最重要的是:可视化编辑器可以轻松处理事情。顶层布局使用包含的xml呈现。
图变厚了
由于包含文件是经典的xml布局文件,这意味着它必须具有一个顶层元素。
因此,如果您的文件需要包含多个小部件,则必须使用布局。
假设
include1.xml
现在有两个TextView
:必须声明一个布局。让我们选择一个LinearLayout
。include1.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:text="Second include"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<TextView
android:id="@+id/textView2"
android:text="More text"
android:textAppearance="?android:attr/textAppearanceMedium"/>
</LinearLayout>
top_level_activity.xml将呈现为:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- First include file -->
<LinearLayout
android:id="@+id/layout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:text="Second include"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<TextView
android:id="@+id/textView2"
android:text="More text"
android:textAppearance="?android:attr/textAppearanceMedium"/>
</LinearLayout>
<!-- Second include file -->
<Button
android:id="@+id/button1"
android:text="Button" />
</LinearLayout>
但是请等一下
LinearLayout
的两个级别是多余的!实际上,两个嵌套的
LinearLayout
毫无用处,因为两个TextView
可以被包含在layout1
下以实现完全相同的渲染。所以,我们能做些什么?
输入合并标记
<merge>
标记只是一个虚拟标记,它提供一个顶级元素来处理这种冗余问题。现在include1.xml变为:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/textView1"
android:text="Second include"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<TextView
android:id="@+id/textView2"
android:text="More text"
android:textAppearance="?android:attr/textAppearanceMedium"/>
</merge>
,现在top_level_activity.xml呈现为:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- First include file -->
<TextView
android:id="@+id/textView1"
android:text="Second include"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<TextView
android:id="@+id/textView2"
android:text="More text"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<!-- Second include file -->
<Button
android:id="@+id/button1"
android:text="Button" />
</LinearLayout>
您保存了一个层次结构级别,避免了一种无用的观点:Romain Guy已经睡得更好了。
您现在不快乐吗?
评论
出色的描述。
– RichieHH
2014年3月16日在0:26
解释很清楚,应该选择答案
–lalitm
2014年5月21日下午5:58
很好,毫无疑问,这应该是公认的答案。
–高拉夫·in那
15年3月17日在9:25
不了解某事..例如,如果外部LinearLayout是垂直的,但是include1.xml中的两个textview应该是水平的呢?在这种情况下,合并不会保存我想要的布局。该怎么办?
–约纳坦·尼尔(Yonatan Nir)
15年7月8日在7:40
显然,@ YonatanNir合并不是您所需要的。如果您确实需要展平视图层次结构,则可以使用RelativeLayout或手动绘制视图
–阿比吉特
15年7月21日在18:30
#3 楼
blazeroni已经说得很清楚了,我只想添加几个要点。<merge>
用于优化布局。它用于减少不必要的嵌套。 将包含
<merge>
标记的布局添加到另一个布局中时,将删除<merge>
节点,并将其子视图直接添加到新的父级。#4 楼
为了更深入地了解正在发生的事情,我创建了以下示例。看一下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,它没有任何作用,并且是多余的。通过Layout Inspector工具查看布局可以清楚地说明这一点。
更新代码以使用合并而不是使用诸如LinearLayout之类的ViewGroup后,content_profile.xml。 >
<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被删除。现在,“布局检查器”工具提供了以下布局层次结构。
因此,当父布局可以放置子布局时,请始终尝试使用合并,或者当您布局子布局时,请更精确地使用合并了解层次结构中将有一个冗余视图组。
#5 楼
使用合并的另一个原因是在ListViews或GridViews中使用自定义视图组时。您可以使用自定义视图,而不是在列表适配器中使用viewHolder模式。定制视图将为根为合并标记的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>
评论
您是否暗示如果在XML文件中使用了RelativeLayout,并且您的自定义ViewGroup继承自RelativeLayout,那么将有两个RelativeLayouts,一个嵌套在另一个中?
– SMBiggs
19年8月1日在22:45
评论
在此示例中,您可以仅使layout2.xml仅包含
–卡鲁
2013年9月12日下午3:37
的确,可以在layout2中使用一个简单的TextView代替,但是那将是完全不同的事情,并且不能作为示例来回答该问题。
–戴夫
13-10-3在14:55
与
– Anshul
2013年12月10日13:04
@Karu:您是对的,在此示例中无需合并标签,但这仅是因为layout2中只有一个元素。如果layout2具有多个元素,则它必须具有一个有效XML的根节点,并且这时merge标签才派上用场。
– gMale
2014年2月22日在16:37
那么如何指定
– IgorGanapolsky
2014年6月10日14:11