相信大家经常听到 include,merge,ViewStub 这样的标签, 官方也提到这三种布局可用于布局的优化. 今天就介绍下这三种布局的使用, 记录下来, 便于后续 app 中的使用.
include 布局重用
app 开发过程中, 会遇到不同页面里有相同的布局, 这时我们可以将这些通用的布局提取出来到一个单独的 layout 文件里, 再使用 <include> 标签引入到相应的页面布局文件里, 主要通过 include 的 layout 属性引用.
举个栗子
include 的布局:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView
- android:id="@+id/tv1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="这里是来自 include 布局" />
- </RelativeLayout>
activity 的布局:
- <?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">
- <TextView
- android:id="@+id/tv2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="以下的内容来自 include 标签" />
- <include
- android:id="@+id/container"
- layout="@layout/include_layout"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/tv"
- android:layout_marginTop="10dp" />
- </RelativeLayout>
这个标签在日常工作使用还是很常见的. 这里有几点需要注意下:
1, 如果给 include 标签 和 include 所加载的布局 都添加 id 的话, 那么 id 要保持一致, 如例子中都是 container, 否则是在代码中获取不到 RelativeLayout 容器的. 当然我们可以避免这样的问题, 只需要给其中一项添加 id 属性就可以.
2,include 布局里元素的 id 要和 include 所在页面布局里的其他元素 id 不同, 如例子中的两个 textview, 如果把 id 设置相同了, 程序运行起来并不会报错, 但是 textview 的赋值只会赋值给其中的一个.
3, 如果需要给 include 标签设置位置属性的话, 如例子中的 layout_below,layout_marginTop, 这时候 必须 同时设置 include 标签的宽高属性 layout_width,layout_height, 否则编译器是会报错的. 一般情况不需要设置 include 的其他属性, 直接加载布局文件
<include layout="@layout/...."/>
4, 布局中可以包含两个相同的 include 标签, 如下代码所示 两个 include 都加载
- layout="@layout/include_layout"
- <?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">
- <TextView
- android:id="@+id/tv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="以下的内容来自 include 标签" />
- <include
- android:id="@+id/container"
- layout="@layout/include_layout"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/tv"
- android:layout_marginTop="10dp" />
- <include
- android:id="@+id/container2"
- layout="@layout/include_layout"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="80dp" />
- </RelativeLayout>
可以设置不同 include 的 id 属性, 引用的时候如下可以正常显示:
- View view = findViewById(R.id.container2);
- TextView textView = view.findViewById(R.id.tv);
- textView.setText("这里是来自 第二个 include 布局");
merge 减少视图层级
merge 标签可用于减少视图层级来优化布局, 可以配合 include 使用, 如果 include 标签的父布局 和 include 布局的根容器是相同类型的, 那么根容器的可以使用 merge 代替.
页面布局
- <?xml version="1.0" encoding="utf-8"?>
- <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:id="@+id/tv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="以下的内容不是来自 merge 标签" />
- <include
- layout="@layout/merge_layout"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="20dp" />
- </LinearLayout>
先看没有使用 merge 的:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- <TextView
- android:id="@+id/tv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="这里是不是来自 merge 布局" />
- </LinearLayout>
看下 view 层的结构:
再看使用了 merge 的:
- <?xml version="1.0" encoding="utf-8"?>
- <merge xmlns:android="http://schemas.android.com/apk/res/android">
- <TextView
- android:id="@+id/tv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="这里是来自 merge 布局" />
- </merge>
view 层结构:
可以看到对比, 减少了一层的 LinearLayout 的嵌套, 需要注意的是使用 merge 的布局, 在 include 的标签设置距离属性没有生效, 可以将一些间距属性设置到 include 布局里元素上, 具体看项目需求使用.
ViewStub 按需加载
按需加载 顾名思义需要的时候再去加载, 不需要的时候可以不用加载, 节约内存使用. 通常情况我们会使用 setVisibility 方法来控制视图的显示和隐藏, 但是这种情况视图已经加载了.
比如 app 中页面里某个布局只需要在特定的情况下才显示, 其余情况下可以不用加载显示, 这时候可以使用 ViewStub.
layout 属性是需要加载布局
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <ViewStub
- android:id="@+id/viewstub"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="20dp"
- android:layout="@layout/viewstub_layout" />
- </LinearLayout>
需要注意的是 ViewStub 的 inflate() 方法只能被调用一次, 一旦调用后, ViewStub 将从视图中移除, 被对应的 layout 布局取代, 同时会保留 ViewStub 上设置的属性效果.
- ViewStub viewstub = findViewById(R.id.viewstub);
- viewstub.inflate();
这篇关于 include,merge,ViewStub 的使用就介绍到这里了, 具体使用情况还得视项目而定.
最后附上 github 地址 https://github.com/taixiang/include
来源: https://www.cnblogs.com/taixiang/p/9221258.html