Google有关ViewStub 的介绍:
“ViewStub 是一种不可视并且大小为 0 的视图,可以延迟到 运行时填充(inflate)布局资源。当 ViewStub
设置为可视或者 inflate() 方法被调用后,就会填充布局资源,然后 ViewStub 便会 被填充的视图替代。”
使用特点:
- 最佳用途就是实现View的延迟加载,避免资源浪费,在需要的时候才加载View
- 如果是经常要来回切换ViewStub的显示和隐藏,ViewStub就不适用
先看一个简单的代码:
MainActivity
public class MainActivity extends AppCompatActivity {
private Button mBtnShow;
private ViewStub mViewStub;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnShow = (Button) findViewById(R.id.btn_show);
mViewStub = (ViewStub) findViewById(R.id.viewStub);
mBtnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//两种方法都可以显示ViewStub中的内容
// mViewStub.inflate();
mViewStub.setVisibility(View.VISIBLE);
}
});
}
}
activity_main.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="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Show ViewStub"
android:textAllCaps="false" />
<ViewStub
android:id="@+id/viewStub"
android:layout="@layout/content"
android:layout_width="match_parent"
android:layout_height="300dp"
android:inflatedId="@+id/content_stub" />
</LinearLayout>
content.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
android:text="ViewStub 是一种不可视并且大小为 0 的视图,可以延迟到 运行时填充(inflate)布局资源。当 ViewStub
设置为可视或者 inflate() 方法被调用后,就会填充布局资源,然后 ViewStub 便会 被填充的视图替代。"
tools:showIn="@layout/activity_main" />
这就是ViewStub的简单使用
需要注意两个异常:
java.lang.IllegalArgumentException: ViewStub must have a valid layoutResource
android:layout=”@layout/content”
ViewStub标签里面用的@layout 前面是android:layout include里面是layout
写错了会抛出上面的异常
java.lang.IllegalStateException: ViewStub must have a non-null ViewGroup viewParent
当ViewStub inflate后,这个ViewStub就从View层次中移除了。(findViewById(R.id.viewStub)也会返回null)
所以MainActivity中mViewStub.inflate(); 应该这样写:
public class MainActivity extends AppCompatActivity {
private Button mBtnShow;
private ViewStub mViewStub;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnShow = (Button) findViewById(R.id.btn_show);
mBtnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mViewStub = (ViewStub) findViewById(R.id.viewStub);
if (mViewStub != null) {
mViewStub.inflate();
}
}
});
}
}
inflate()和setVisibility(View.VISIBLE);
这两个放到都可以显示ViewStub的视图
setVisibility(View.VISIBLE)会调用inflate()方法
inflate()方法可以返回当前的View
View stubView = mViewStub.inflate();
ViewStub中的layout_width 和 layout_height
来上一张图:
我在ViewStub标签里面的width和height如下:
android:layout_width="match_parent"
android:layout_height="300dp"
在@layout/content中如下
android:layout_width="match_parent"
android:layout_height="match_parent"
可以看到, ViewStub标签里面的width和height属性会覆盖掉填充的布局的属性.
android:inflatedId=”@+id/content_stub”
mBtnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mViewStub = (ViewStub) findViewById(R.id.viewStub);
if (mViewStub != null) {
mViewStub.inflate();
((TextView) findViewById(R.id.content_stub)).setText("我只是一个不明真相的吃瓜群众");
}
}
});
现在把 android:inflatedId=”@+id/content_stub” 去掉
mBtnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mViewStub = (ViewStub) findViewById(R.id.viewStub);
if (mViewStub != null) {
mViewStub.inflate();
((TextView) findViewById(R.id.tv_content)).setText("我只是一个不明真相的吃瓜群众");
}
}
});
可以看到, android:inflatedId=”@+id/content_stub”会覆盖content.xml中根元素的id属性, 这个属性可以不添加.
再看这里
mBtnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mViewStub = (ViewStub) findViewById(R.id.viewStub);
if (mViewStub != null) {
((TextView) mViewStub.inflate()).setText("我只是一个不明真相的吃瓜群众");
}
}
});
可以看到, mViewStub.inflate()返回的也是content.xml中的TextView.(content.xml的根元素)