一、include的用法以及注意点
官网文档:通过 <include> 重复使用布局
include标签是用来解决布局复用的。在开发Android布局时,我们常将一些通用的视图提取到一个单独的layout文件中,然后使用标签在需要使用的其他layout布局文件中加载进来。这样,便于对相同视图内容进行统一的控制管理,提高布局重用性。
下面我们以头部导航栏为例,抽取布局如下:
title.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="返回" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="提示文字"
android:textSize="20sp" />
</RelativeLayout>
使用也比较简单,如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include
android:layout_width="match_parent"
android:layout_height="40dp"
layout="@layout/title" />
</RelativeLayout>
include标签使用注意点:
1.标签当中,可以重写所有layout属性的,如上面include中指定的layout属性将会覆盖掉title中指定的layout属性。 而非layout属性则无法在标签当中进行覆写。另外需要注意的是,如果我们想要在标签当中覆写layout属性, 必须要将layout_width和layout_height这两个属性也进行覆写,否则覆写效果将不会生效。
2.一个xml布局文件有多个include标签需要设置ID,才能找到相应子View的控件,否则只能找到第一个include的layout布局,以及该布局的控件。
3.如果我们给include所加载的layout布局的根容器设置了id属性,也在include标签中设置了id属性,同时需要在代码中获取根容器的控件对象时,最好将这两个id设置相同的名称!否则,可能获取不到根容器对象,即为null。
二、merge的用法以及注意点
在一个布局中添加另一个布局时,<merge>
标记有助于消除视图层次结构中的冗余视图组。<merge>
的一个用例是,通过扩展 ViewGroup
实现自定义视图。
例如,如果您的主布局是一个垂直 LinearLayout,其中两个连续视图可以在多个布局中重复使用,那么放置这两个视图的可重复使用布局需要有自己的根视图。不过,如果使用另一个 LinearLayout
作为可重复使用的布局的根视图,则会导致垂直 LinearLayout
内出现垂直 LinearLayout
。嵌套的 LinearLayout
没有实际用处,而且会降低界面性能。
相反,您可以扩展 LinearLayout
以创建自定义视图,并使用布局 XML 来描述其子视图。XML 中的顶部标记是 <merge>
,而不是 LinearLayout
,如以下示例所示:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/add"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/delete"/>
</merge>
merge标签使用注意点:
1.根布局是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity的ContentView父元素就是FrameLayout,所以可以用merge消除只剩一个.
2.因为merge标签并不是View,所以在通过LayoutInflate.inflate()方法渲染的时候,第二个参数必须指定一个父容器,且第三个参数必须为true,也就是必须为merge下的视图指定一个父亲节点.由于merge不是View所以****对merge标签设置的所有属性都是无效的.
3.merge标签必须使用在根布局,并且ViewStub标签中的layout布局不能使用merge标签.
三、ViewStub的用法以及注意点
官网文档:按需加载视图
有时,您的布局需要很少使用的复杂视图。无论是作品详情、进度指示器还是撤消消息,您都可以通过仅在需要时加载这些视图来减少内存使用量并加快渲染速度。
如果您有应用将来需要的复杂视图,可以通过为复杂且很少使用的视图定义 [ViewStub]
来延迟加载资源。
假设您有一个布局,希望在应用的用户体验历程的后续阶段加载:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv"
android:src="@drawable/logo"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
您可以使用以下 ViewStub 推迟加载。如需让它显示或加载任何内容,您必须使其显示引用的布局:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ViewStub
android:id="@+id/stub_import"
android:inflatedId="@+id/panel_import"
android:layout="@layout/heavy_layout_we_want_to_postpone"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
</FrameLayout>
activity中代码如下:
public void show(View view){
//
ViewStub stub = ((ViewStub) findViewById(R.id.stub_import));
if(stub!=null){
View stubView = stub.inflate();
ImageView address = (ImageView ) stubView.findViewById(R.id.iv);
}
}
ViewStub标签使用注意点:
- ViewStub标签不支持merge标签。因此这有可能导致加载出来的布局存在着多余的嵌套结构,具体如何去取舍就要根据各自的实际情况来决定了。
- ViewStub的inflate只能被调用一次,第二次调用会抛出异常。
- 虽然ViewStub是不占用任何空间的,但是每个布局都必须要指定layout_width和layout_height属性,否则运行就会报错。
总结
1.使用include标签重用布局
2.使用merge标签避免冗余的布局嵌套
3.使用ViewStub实现按需加载