ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。
1优点
ViewStub,惰性装载控件。ViewStub是一个无形的、零大小的视图,可以在程序运行的过程中,通过懒加载的模式inflate进布局资源中。当一个ViewStub的inflate()方法被调用或者被设为显示时,这个ViewStub使用设定的View才会被加载,并替换当前ViewStub的位置。因此,ViewStub存在于视图层次,直到setVisibility(int)或inflate()方法被调用,否则是不加载控件的,所以消耗的资源小。通常也叫它为“懒惰的include”。
2基础练习
不错的讲ViewStub基础的博文
这里将博文里强调的问题,再唠叨一遍咯:
使用的时候的注意事项:
. 某些布局属性要加在ViewStub而不是实际的布局上面,才会起作用,比如上面用的android:layout_margin*系列属性,如果加在TextView上面,则不会起作用,需要放在它的ViewStub上面才会起作用。而ViewStub的属性在inflate()后会都传给相应的布局。
3属性
<ViewStub
android:id="@+id/stub"
android:inflatedId="@+id/subTree"
android:layout="@layout/mySubTree"
android:layout_width="120dip"
android:layout_height="40dip" />
id:可以找到此viewStub控件
inflatedId:当控件inflate之后,可以通过这个inflatedId找到其layout。
layout:inflate之后,将原viewStub移除,获得layout布局。
注:
1.View inflated = stub.inflate();//inflate返回的是view
2.加载view之后,viewstub本身就会被新加载进来的view替换掉
官方解释:When inflate() is invoked, the ViewStub is replaced by the inflated View and the inflated View is returned. This lets applications get a reference to the inflated View without executing an extra findViewById().
4 监听事件
对于ViewStub而言,它需要监听的事件就只有一个,被加载的时候触发的事件VIewStub.OnInflateListener,在这个事件中,需要实现一个onInflate()方法,例如:
sTubText.setOnInflateListener(new ViewStub.OnInflateListener() {
@Override
public void onInflate(ViewStub stub, View inflated) {
}
});
5 onInflate()和setVisibility()的区别
当setVisibility(int)或inflate()方法被调用之后,这个ViewStub在布局中将被使用指定的View替换,所以inflate过一遍的ViewStub,如果被隐藏之后再次想要显示,将不能使用inflate()方法,但是可以再次使用setVisibility(int)方法设置为可见。
仅第一次需要inflate(),可以通过判断异常来处理:
try {
//如果没有被inflate过,使用inflate膨胀
LinearLayout layout=(LinearLayout)viewStub.inflate();
RatingBar bar=(RatingBar)layout.findViewById(R.id.ratingBar1);
bar.setNumStars(4);
} catch (Exception e) {
//如果使用inflate膨胀报错,就说明已经被膨胀过了,使用setVisibility方法显示
viewStub.setVisibility(View.VISIBLE);
}
或者只用setVisibility方法,缺点是不能像inflate()一样返回layout,需要findViewByID(inflatedId)来获得。
注:setVisibility会间接调用inflate。
6.代码示例:
MainActivity:
public class MainActivity extends Activity implements View.OnClickListener {
private ViewStub sTubText;
private ViewStub sTubImg;
private Button btn1;
private Button btn2;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sTubText = (ViewStub) findViewById(R.id.viewsub_text);
sTubImg = (ViewStub) findViewById(R.id.viewsub_img);
btn1 = (Button) findViewById(R.id.btn_1);
btn2 = (Button) findViewById(R.id.btn_2);
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
sTubText.setOnInflateListener(new ViewStub.OnInflateListener() {//只监听调用inflate时,调用visible时不能监听到。
@Override
public void onInflate(ViewStub stub, View inflated) {
Toast.makeText(getApplicationContext(), "加载了view", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_1:
sTubText.setVisibility(View.VISIBLE);//间接调用了inflate()方法。使用下面屏蔽的方法也行。
// try {
// View view = sTubText.inflate();
// textView = (TextView) view.findViewById(R.id.text);
// textView.setText("打开了!!!");
// } catch (Exception e) {
// sTubText.setVisibility(View.VISIBLE);
// }
break;
case R.id.btn_2:
sTubText.setVisibility(View.GONE);
break;
}
}
}
main布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.viewsubtest.MainActivity">
<Button
android:id="@+id/btn_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="显示"/>
<Button
android:id="@+id/btn_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="隐藏"/>
<ViewStub
android:id="@+id/viewsub_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout="@layout/layout_viewsub_text"/>
</RelativeLayout>
viewStub关联的布局:
<?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="horizontal">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="viewSub测试文字"
android:textSize="20dp"
/>
</LinearLayout>
效果: