Android ViewStub

分享到:

ViewStub控件本身是不可见的,ViewStub通过inflate()方法初始化一个布局文件,一但ViewStub调用了inflate()方法它自身就没用了,同时会把写在自身的属性传递到内部的布局控件上,此时ViewStub内部包含的布局才会被初始化。解释起来有些诡异,大家肯定会想为什么会存在这么奇怪的控件。
或许可以这么解释:
当开发一个非常复杂的APP时,UI界面上包含10个以上的控件,这些控件可能不会同时显通常把一些控件的可见性设为View.GONE,以此来达到隐藏的效果,然后等待某个合适的时机再设置为可见。这么做表面上看起来很合理但是大家都忽略一点,就算把控件的初始状态设为不可见同样会被初始化,一样会消耗硬件资源严重的会导致整个APP运行卡顿。ViewStub这时就应运而生了,把不需要立即初始化的布局view放到这里面来,Activity在初始化过程中就会掠过这些控件,相当于被隔离了。需要使用时调用ViewStub的inflate()方法即可。所以可认为ViewStub是为优化APP性能而产生的。

下面通过一个例子说明ViewStub的用法。(本例源码从互联网收集整理而来
这个例子主要包含4个文件,
(1)主界面布局,含两个ViewStub
(2)TextView子布局,包含一个TextView控件,用来被ViewStub调用
(3)ImageView子布局,包含一个ImageView控件,用来被ViewStub调用
(4)Activity源码。
主界面XML布局代码:

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal">
<ViewStub
android:id="@+id/viewstub_demo_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_marginTop="10dip"
android:layout="@layout/viewstub_demo_text_layout"/>
<ViewStub
android:id="@+id/viewstub_demo_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout="@layout/viewstub_demo_image_layout"/>
</LinearLayout>

TextView布局:

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/viewstub_demo_textview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#aa664411"
android:textSize="16sp"/>
</LinearLayout>

ImageView布局:

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/viewstub_demo_imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

Activity代码:

package com.effective;  

import android.app.Activity;
import android.os.Bundle;
import android.view.ViewStub;
import android.widget.ImageView;
import android.widget.TextView;

public class ViewStubDemoActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewstub_demo_activity);
if ((((int) (Math.random() * 100)) & 0x01) == 0) {
// to show text
// all you have to do is inflate the ViewStub for textview
ViewStub stub = (ViewStub) findViewById(R.id.viewstub_demo_text);
stub.inflate();
TextView text = (TextView) findViewById(R.id.viewstub_demo_textview);
text.setText("The tree of liberty must be refreshed from time to time" +
" with the blood of patroits and tyrants! Freedom is nothing but " +
"a chance to be better!");
} else {
// to show image
// all you have to do is inflate the ViewStub for imageview
ViewStub stub = (ViewStub) findViewById(R.id.viewstub_demo_image);
stub.inflate();
ImageView image = (ImageView) findViewById(R.id.viewstub_demo_imageview);
image.setImageResource(R.drawable.happy_running_dog);
}
}
}

运行效果如下:


最后总结一下使用ViewStub的要领:
(1) ViewStub只能用来Inflate一个布局文件,而不是某个具体的View控件,当然也可以把单个控件写在某个布局文件中再调用。

(2) 某些布局属性要加在ViewStub而不是实际的布局上面,才会起作用,比如上面用的android:layout_margin系列属性,如果加在TextView上面,则不会起作用,需要放在它的ViewStub上面才会起作用。而ViewStub的属性在inflate()后会都传给相应的布局。

(3) ViewStub只能Inflate一次,之后ViewStub对象会被置为空。按句话说,某个被ViewStub指定的布局被Inflate后,就不会够再通过ViewStub来控制它了所以无法指望后面接着使用ViewStub来控制布局。所以当需要在运行时不止一次的显示和隐藏某个布局,那么ViewStub是做不到的。这时就只能使用View的可见性来控制了。

昵    称:
验证码:

相关文档:

Android控件
Android基础知识
Android组件
Android实例