布局优化神器 include 、merge、ViewStub标签详解
来源:互联网 发布:易学入门知乎 编辑:程序博客网 时间:2024/06/07 18:29
导读
在日常开发中,我们可能会遇到有很多相似的布局,如果我们每一个XML文件都写一次,不说麻烦,代码也显得冗余,而且可读性也很差.这时候我们该怎么弄,本编文章将会介绍include、merge和ViewStub标签的用法供大家参考学习…!
Tips
使用Android Studio 的同学,可以直接在布局文件对应控件:
右键 -> Refactor -> Extract -> Style 抽取样式
右键 -> Refactor -> Extract -> Layout 抽取布局 include标签
include标签
include标签常用于将布局中的公共部分提取出来供其他layout共用,以实现布局模块化,也是平常我们设计布局时用的最多的
include 官方文档
include标签使用:
一、定义要实现(抽取)的layout布局:
//include_test.xml<?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="wrap_content" android:gravity="center_horizontal" android:orientation="vertical"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="@string/textview" android:textSize="24sp"/> <EditText android:id="@+id/editText" android:hint="@string/divide" android:layout_width="300dp" android:layout_height="wrap_content"/></LinearLayout>---------------------------------------------------------------//include_text_relative<?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="wrap_content" android:gravity="center_horizontal" > <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="TextView_Relative" android:textSize="24sp"/> <EditText android:id="@+id/editText" android:layout_width="300dp" android:layout_height="wrap_content" android:layout_below="@+id/textView" android:hint="@string/divide"/></RelativeLayout>---------------------------------------------------------------//include_toolbar.xml<?xml version="1.0" encoding="utf-8"?><android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/tb_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="#00f" app:theme="@style/AppTheme" app:title="这是一个ToolBar" app:titleTextColor="@android:color/white"/>
二、Activity的XML布局文件调用include标签:
<?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" > <!--测试layout和<include>都设置ID的情况--> <include android:id="@+id/tb_toolbar" layout="@layout/include_toolbar"/> <!--如果只有单个include 这样写就可以,加载的布局的子View,直接findViewByID就能找到--> <include layout="@layout/include_text"/> <!--如果有多个include,需要添加ID属性--> <include android:id="@+id/include_text1" layout="@layout/include_text"/> <!--这个layout用RelativeLayout 实现--> <!--如果要使用layout_margin这样的属性,要同时加上layout_w/h属性,不然没反应--> <include android:id="@+id/include_text2" layout="@layout/include_text_relative" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="50dp"/></LinearLayout>
三、Activity中调用include标签layout中的子View:
private void initView() { //如果include布局根容器和include标签中的id设置的是不同的值,这里获取的mToolbar值将为null Toolbar mToolbar = (Toolbar) findViewById(R.id.tb_toolbar); setSupportActionBar(mToolbar); //普通include标签用法,直接拿子View属性实现 TextView textView = (TextView) findViewById(R.id.textView); textView.setText("不加ID实现的include标签"); //多个include标签用法,添加ID,findViewByID找到layout,再找子控件 View view_include = findViewById(R.id.include_text1); TextView view_include_textView = (TextView) view_include.findViewById(R.id.textView); view_include_textView.setText("加了ID实现的include标签"); //多个include标签用法,添加ID,findViewByID找到layout,再找子控件 View view_include_Relative = findViewById(R.id.include_text2); TextView view_textView_relative = (TextView) view_include_Relative.findViewById(R.id.textView); view_textView_relative.setText("加了ID实现的include标签(RelaviteLayout)"); }
include标签Demo效果图
==include使用注意==
- 一个xml布局文件有多个include标签需要设置ID,才能找到相应子View的控件,否则只能找到第一个include的layout布局,以及该布局的控件
- include标签如果使用layout_xx属性,会覆盖被include的xml文件根节点对应的layout_xx属性,建议在include标签调用的布局设置好宽高位置,防止不必要的bug
- include 添加id,会覆盖被include的xml文件根节点ID,这里建议include和被include覆盖的xml文件根节点设置同名的ID,不然有可能会报空指针异常
- 如果要在include标签下使用RelativeLayout,如layout_margin等其他属性,记得要同时设置layout_width和layout_height,不然其它属性会没反应
merge 标签
merge标签主要用于辅助include标签,在使用include后可能导致布局嵌套过多,多余的layout节点或导致解析变慢(可通过hierarchy viewer工具查看布局的嵌套情况)
官方文档说明:merge用于消除视图层次结构中的冗余视图,例如根布局是Linearlayout,那么我们又include一个LinerLayout布局就没意义了,反而会减慢UI加载速度
merge 官方文档
merge标签常用场景:
根布局是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity的ContentView父元素就是FrameLayout,所以可以用merge消除只剩一个.
某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自动被忽略,而将其子节点全部合并到主布局中.
自定义View如果继承LinearLayout(ViewGroup),建议让自定义View的布局文件根布局设置成merge,这样能少一层结点.
merge标签使用:
在XML布局文件的根布局如RelativeLayout直接改成merge即可
merge标签使用前后Hierarchy Viewer截图
FrameLayout 替换 merge 前
FrameLayout 替换 merge 后
include 标签对应 layout 根布局 替换 merge 前
include 标签对应 layout 根布局 替换 merge 后
==merge使用注意==
- 因为merge标签并不是View,所以在通过LayoutInflate.inflate()方法渲染的时候,第二个参数必须指定一个父容器,且第三个参数必须为true,也就是必须为merge下的视图指定一个父亲节点.
- 因为merge不是View,所以对merge标签设置的所有属性都是无效的.
- 注意如果include的layout用了merge,调用include的根布局也使用了merge标签,那么就失去布局的属性了
- merge标签必须使用在根布局
- ViewStub标签中的layout布局不能使用merge标签
ViewStub 标签
ViewStub 标签最大的优点是当你需要时才会加载,使用它并不会影响UI初始化时的性能.各种不常用的布局像进度条、显示错误消息等可以使用ViewStub标签,以减少内存使用量,加快渲染速度.ViewStub是一个不可见的,实际上是把宽高设置为0的View.效果有点类似普通的view.setVisible(),但性能体验提高不少
第一次初始化时,初始化的是ViewStub View,当我们调用inflate()或setVisibility()后会被remove掉,然后在将其中的layout加到当前view hierarchy中
ViewStub 官方文档链接
//官方例子<ViewStub android:id="@+id/stub_import" <!--android:inflateId:重写ViewStub的父布局控件的Id--> android:inflatedId="@+id/panel_import" < <!--android:layout:设置ViewStub被inflate的布局--> android:layout="@layout/progress_overlay" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" /> ------------------------------------------------- //当你想加载布局时,可以使用下面其中一种方法: ((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE); // or View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
- 判断ViewStub(做单例)是否已经加载过:
- 如果通过setVisibility来加载,那么通过判断可见性即可;
- 如果通过inflate()来加载,判断ViewStub 的ID是否为null来判断(findViewById(…))
public class ViewStubActivity extends AppCompatActivity implements View.OnClickListener, ViewStub.OnInflateListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view_stub); } private View networkErrorView; private void showNetError() { // not repeated infalte if (networkErrorView != null) { //setVisibility()方式加载布局,加载次数不限 networkErrorView.setVisibility(View.VISIBLE); return; } //inflate()方式加载布局,只能加载一次 ViewStub stub = (ViewStub) findViewById(R.id.network_error_layout); stub.setOnInflateListener(this); networkErrorView = stub.inflate(); Button networkSetting = (Button) networkErrorView.findViewById(R.id.network_miss); networkSetting.setOnClickListener(this); Button refresh = (Button) findViewById(R.id.network_refresh); refresh.setOnClickListener(this); } private void showNormal() { if (networkErrorView != null) { networkErrorView.setVisibility(View.GONE); } } public void show(View view) { showNetError(); } public void refresh(View view) { showNormal(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.network_miss: Toast.makeText(this, "network_miss", Toast.LENGTH_SHORT).show(); break; case R.id.network_refresh: Toast.makeText(this, "network_refresh", Toast.LENGTH_SHORT).show(); break; } } /** * * @param stub 当前待inflate的ViewStub控件 * @param inflated 当前被inflate的View视图 */ @Override public void onInflate(ViewStub stub, View inflated) { }}
ViewStub标签Demo效果图:
ViewStub标签使用前后Hierarchy Viewer截图
- ViewStub标签使用前
- ViewStub标签使用后
==ViewStub标签使用注意==
- ViewStub标签不支持merge标签
- ViewStub的inflate只能被调用一次,第二次调用会抛出异常,setVisibility可以被调用多次,但不建议这么做(ViewStub 调用过后,可能被GC掉,再调用setVisibility()会报异常)
- 为ViewStub赋值的android:layout_XX属性会替换待加载布局文件的根节点对应的属性
总结
本篇Demo源码
导入Moudle的方式导入工程
本篇文章到此结束,欢迎关注,后续有补充的会即使更新,有问题也欢迎评论,共同成长
Hierarchy Viewer工具使用
- 布局优化神器 include 、merge、ViewStub标签详解
- android 布局优化标签<include/>、<merge />、<ViewStub />
- Android 布局优化 include,merge,viewstub标签
- include、ViewStub、merge优化布局标签
- Android布局:include、merge 、ViewStub标签区别
- Android-布局优化(include , merge , ViewStub)
- Android 布局优化之include、merge、ViewStub
- 布局优化技巧--<include>/<merge>/<viewStub>
- 使用include、merge、ViewStub优化布局
- Android之布局优化include、merge 、ViewStub
- 布局优化——include、merge 、ViewStub
- 安卓布局优化Include merge ViewStub
- Android布局优化之include、ViewStub、merge
- 布局优化偏------------- include、merge 、ViewStub
- Android使用include/merge/ViewStub优化布局
- Android布局优化技巧--<include>/<merge>/<viewStub>
- 布局优化:使用include、merge、ViewStub
- Android布局的优化-include、merge、ViewStub
- [YTU]_2631( B1 能存各种类型数据的Store类)
- 解决ScrollView加载完数据后会滑到下面
- Haskell学习笔记 --- 基础语法篇二
- xgboost--API
- nginx proxy_next_upstream
- 布局优化神器 include 、merge、ViewStub标签详解
- C++ 测试试卷二
- OC项目集成第三方换肤框架:SwiftTheme(swift编写,兼容OC)教程
- [YTU]_2613( 距离产生美)
- wsdl生成客户端代码
- C#编程向SQLite数据库中正确写入DateTime类型数据
- 026-Java-017
- 欢迎使用CSDN-markdown编辑器
- Java链表来存储二叉树和(前中后序)遍历二叉树--Java版