Android ViewStub

01. 简介

A ViewStub is an invisible, zero-sized View that can be used to lazily inflate layout resources at runtime.

控件 ViewStub 是一个不可见的,零尺寸的 View 它可以在运行时进行延迟加载。

When a ViewStub is made visible , or when inflate() is invoked, the layout resource is inflated. The ViewStub then replaces itself in its parent with the inflated View or Views.

当 ViewStub 的 setVisibility(int) 方法或者 inflate() 方法被调用,它会加载被指定的布局并在父布局中将自己替换为加载的布局。

Therefore, the ViewStub exists in the view hierarchy until setVisibility(int) or inflate() is invoked.

替换后,控件 ViewStub 会从布局树中移除。

The inflated View is added to the ViewStub's parent with the ViewStub's layout parameters.

控件 ViewStub 的布局属性会传递给被加载的布局。

因此,不是必须显示的布局使用 ViewStub 代替后减少界面首次加载时资源消耗,提升最初加载速度。

02. 用法

布局

android:id="@+id/viewStub"

android:layout_width="match_parent"

android:layout_height="50dp"

android:layout_marginTop="10dp"

android:inflatedId="@+id/titleBar"

android:layout="@layout/just_title" />

android:layout 指定被加载替换的布局

android:inflatedId 指定被加载替换的布局的 id

加载

viewStub = (ViewStub) findViewById(R.id.viewStub);

View inflated = stub.inflate();

官方推荐加载首选方法

调用 inflate() 方法后布局被加载替换同时返回布局对象。避免了使用 findViewById() 方法。

该 inflate() 方法只能调用一次,调用被移除而没有了父布局。第二次调用会抛出异常 ViewStub must have a non-null ViewGroup viewParent 。

03. 示例

主界面布局

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/viewStub"

android:layout_width="match_parent"

android:layout_height="50dp"

android:layout_marginTop="10dp"

android:inflatedId="@+id/titleBar"

android:layout="@layout/just_title" />

android:id="@+id/bt_show"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="80dp"

android:text="Show"

android:textAllCaps="false" />

android:id="@+id/bt_hide"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_below="@id/bt_show"

android:layout_marginTop="10dp"

android:text="Hide"

android:textAllCaps="false" />

被替换布局 just_title.xml

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="50dp"

android:background="@color/colorPrimary">

android:id="@+id/tv_show_title"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerHorizontal="true"

android:layout_centerVertical="true"

android:ellipsize="end"

android:singleLine="true"

android:textColor="@android:color/white"

android:textSize="20sp"

tools:text="Title" />

界面加载

public class ViewStubActivity extends AppCompatActivity implements View.OnClickListener {

private ViewStub viewStub;// 占位控件

private Button bt_show;// 显示按钮

private Button bt_hide;// 隐藏按钮

private TextView tv_show_title;// 标题

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_view_stub);

viewStub = (ViewStub) findViewById(R.id.viewStub);// 寻找控件

bt_show = (Button) findViewById(R.id.bt_show);

bt_hide = (Button) findViewById(R.id.bt_hide);

bt_show.setOnClickListener(this);

bt_hide.setOnClickListener(this);

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.bt_show:// 显示

try {

View titleBar = viewStub.inflate();// 第二次加载会抛出异常

tv_show_title = (TextView) titleBar.findViewById(R.id.tv_show_title);

tv_show_title.setText("Title");

} catch (Exception e) {

viewStub.setVisibility(View.VISIBLE);

}

break;

case R.id.bt_hide:// 隐藏

viewStub.setVisibility(View.GONE);

break;

}

}

}

隐藏

ViewStubHide

显示

ViewStubShow

更换加载方式

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.bt_show:// 显示

viewStub.setVisibility(View.VISIBLE);// 方式二

if (tv_show_title == null) {

tv_show_title = (TextView) findViewById(R.id.tv_show_title);

tv_show_title.setText("Title");

}

break;

}

}

04. 监听

加载监听回调

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_view_stub);

viewStub = (ViewStub) findViewById(R.id.viewStub);// 寻找控件

// 设置加载监听回调,成功加载后回调[只会回调一次]

viewStub.setOnInflateListener(new ViewStub.OnInflateListener() {

/**

* Listener used to receive a notification after a ViewStub has successfully inflated its layout resource.

*

* @param stub ViewStub 对象

* @param inflated 被加载填充的布局

*/

@Override

public void onInflate(ViewStub stub, View inflated) {

tv_show_title = (TextView) inflated.findViewById(R.id.tv_show_title);

tv_show_title.setText("ShowTitle");

}

});

}

按需使用

05. 源码

setVisibility() 方法

public void setVisibility(int visibility) {

if (mInflatedViewRef != null) {// 第二次就不空

View view = mInflatedViewRef.get();

if (view != null) {

view.setVisibility(visibility);// 不空直接显示

} else {

throw new IllegalStateException("setVisibility called on un-referenced view");

}

} else {// 第一次会为空

super.setVisibility(visibility);

if (visibility == VISIBLE || visibility == INVISIBLE) {

inflate();// 调用填充方法

}

}

}

inflate() 方法

public View inflate() {

final ViewParent viewParent = getParent();// 获取父布局。第一次加载后从视图树中移除。第二次便没有了父布局。

if (viewParent != null && viewParent instanceof ViewGroup) {// 父布局不空。第二次为空。

if (mLayoutResource != 0) {// 被指定的布局

final ViewGroup parent = (ViewGroup) viewParent;

final LayoutInflater factory;// 布局填充器

if (mInflater != null) {

factory = mInflater;

} else {

factory = LayoutInflater.from(mContext);// 获取布局填充器

}

final View view = factory.inflate(mLayoutResource, parent,

false);// 加载布局

if (mInflatedId != NO_ID) {// 被指定的布局的 ID

view.setId(mInflatedId);// 即 android:inflatedId 指定的新 ID

}

final int index = parent.indexOfChild(this);// 获取位置

parent.removeViewInLayout(this);// 移除 ViewStub 自己

final ViewGroup.LayoutParams layoutParams = getLayoutParams();// ViewStub 指定的布局参数

if (layoutParams != null) {

parent.addView(view, index, layoutParams);// 指定位置和参数填充

} else {

parent.addView(view, index);

}

mInflatedViewRef = new WeakReference(view);// 弱引用

if (mInflateListener != null) {// 监听器不空

mInflateListener.onInflate(this, view);// 监听回调。所以只回调一次。

}

return view;// 加载的布局返回

} else {// 没有指定填充的布局就抛出异常

throw new IllegalArgumentException("ViewStub must have a valid layoutResource");

}

} else {// 父布局为空就抛出异常

throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");

}

}

06. 注意

ViewStub 支持使用 标签的布局。

ViewStub 不支持使用 标签的布局。

07. 参考

android support v4 viewstub,Android 控件ViewStub相关推荐

  1. android.support.v4作用,Android Support V4, V7, V13的作用与用法

    1, Android Support V4, V7, V13是什么? 本质上就是三个java library. 2,  为什么要有support库? 如果在低版本Android平台上开发一个应用程序, ...

  2. 【Android】Anroid5.0+新控件---酷炫标题栏的简单学习

    Android5.0+推出的新控件感觉特别酷,最近想模仿大神做个看图App出来,所以先把这些新控件用熟悉了. 新控件的介绍.使用等等网上相应的文章已经特别多了,题主也没那能力去写篇详解出来,本篇随笔记 ...

  3. The type android.support.v4.view.ScrollingView cannot be resolved. It is indirectly referenced from

    前几天另一个项目使用RecyclerView控件,引用类库然后继承一切都很顺序 详细:http://www.cnblogs.com/freexiaoyu/p/5022602.html 今天打算将另一个 ...

  4. Android 解决下拉刷新控件和ScrollVIew的滑动冲突问题。

    最近项目要实现ScrollView中嵌套广告轮播图+RecyleView卡片布局,并且RecyleView按照header和内容的排列样式,因为RecyleView的可扩展性很强,所以我毫无疑问的选择 ...

  5. Android自定义多TAB悬浮控件实现蘑菇街首页效果

    原文:http://www.cnblogs.com/ImyFen/archive/2015/11/15/4967127.html 说明: 1.viewpager不能左右滑动: 2.转载时代码略有改动( ...

  6. Android SwipeRefreshLayout下拉刷新控件源码简单分析

    咱们在做Android APP开发的时候经常碰到有下拉刷新和上拉加载跟多的需求,这篇文章咱们先说说下来刷新,咱们就以google的原生的下拉刷新控件SwipeRefreshLayout来看看大概的实现 ...

  7. Android Support v4\v7\v13和AndroidX的区别及应用场景

    前言 Google提供了Android Support Library package 系列的包来保证来高版本sdk开发的向下兼容性,即我们用4.x开发时,在1.6等版本上,可以使用高版本的有些特性, ...

  8. Android Support v4、v7、v13的区别和应用场景

    google提供了Android Support Library package 系列的包来保证来高版本sdk开发的向下兼容性,即我们用4.x开发时,在1.6等版本上,可以使用高版本的有些特性,如fr ...

  9. Android Support v4、v7、v13 介绍

     google提供了Android Support Library package 系列的包来保证来高版本sdk开发的向下兼容性,即我们用4.x开发时,在1.6等版本上,可以使用高版本的有些特性, ...

最新文章

  1. Exchange服务器系列课程之七--维护邮件服务器(二)
  2. codeforces水题100道 第五题 Codeforces Round #304 (Div. 2) A. Soldier and Bananas (math)
  3. 4月23日遇到的问题
  4. 2.4.4 死锁的处理策略-检测和解除
  5. 如何写第一个scrapy
  6. xxl子任务_XXL-JOB v2.0.2,分布式任务调度平台 | 多项特性优化更新
  7. 『设计模式』备忘录模式(memento)下象棋,我就想悔棋怎么办
  8. Cloud一分钟 | 一脚踏入云计算2.0时代,京东云这回拼的是“朋友 圈”;8400万元私有云招标...
  9. mysql主键unsigned_mysql – 主键应该总是unsigned?
  10. 评分模型的监控报表汇总
  11. FastCGI 使用介绍
  12. unity3d 人物对话_RPG角色对话编辑器系统RPG Conversation/Dialogue Editor 1.2.0
  13. 美赛数学建模O奖论文下载
  14. 下载kaggle数据集
  15. 数值分析——三角分解法(LU分解法)C++
  16. linux系统权限640,linux权限及权限管理
  17. Python Day05习题
  18. 未曾读过刘备的人,不足以谈人生
  19. c语言 srand was not,c语言srand生成随机数的问题
  20. 计算机在通风网络中的应用,普适计算在煤矿通风网络解算中的应用研究

热门文章

  1. win10下Redis安装、启动教程
  2. javascript中的复制
  3. 【抄】更改eclipse配置
  4. Git之Reset的三种模式
  5. CleanCodeHandbook Chapter 9: Binary Search(48-50)
  6. 【机房收费系统】--SSTab控件与MSHFlexGrid控件
  7. Python:[-1]、[:-1]、[::-1]、[n::-1] 原理大详解(超全超仔细!)
  8. Visual Studio C++6.0下载地址
  9. 一文搞懂List 、ListObject、List?的区别以及? extends T与? super T的区别
  10. 提高设计档次的8个方法