android support v4 viewstub,Android 控件ViewStub

d1b683016b10

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;

}

}

}

隐藏

d1b683016b10

ViewStubHide

显示

d1b683016b10

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. 参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值