ViewStub 是一个轻量级的View,View 的宽高为0,不绘制任何东西,只是占一个位置而已。
优势
在需要的时候才加载View,这样实现了View的延迟加载,避免资源的浪费,减少渲染时间, 因此可以提高页面的加载速度。
不足
ViewStub所要替代的layout文件中不能有标签,
ViewStub在加载完后会被移除,或者说是被加载进来的layout替换掉了
<ViewStub
android:id="@+id/view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/stub_view_container"/>
用ViewStub加载layout文件时,可以调用 viewStub.setVisibility(View.VISIBLE) 或者 viewStub.inflate()
一旦ViewStub visible/inflated,则ViewStub将从视图框架中移除,其id view_stub 也会失效
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_marginTop="10dp"
android:text="显示ViewStub"/>
<ViewStub
android:id="@+id/view_stub"
android:inflatedId="@+id/stub_new"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/stub_view_container"/>
LinearLayout>
"http://schemas.android.com/apk/res/android"
android:id="@+id/stub_old"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
id="@+id/stub_container1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:text="Stub Container1"/>
id="@+id/stub_container2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:layout_below="@+id/stub_container1"
android:text="Stub Container2"/>
public class MainActivity extends AppCompatActivity {
public static String TAG = "OWEN";
ViewStub viewStub;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewStub = (ViewStub) findViewById(R.id.view_stub);
Log.e(TAG, "viewStub: " + findViewById(R.id.view_stub));
Log.e(TAG, "layout: " + findViewById(R.id.stub_new));
findViewById(R.id.text_view).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
viewStub.inflate();
//viewStub.setVisibility(View.VISIBLE);
Log.e(TAG, "viewStub: " + viewStub);
Log.e(TAG, "find viewStub: " + findViewById(R.id.view_stub));
}
});
}
}
打印结果
09-27 11:49:39.414 2275-2275/com.owen.provider E/OWEN: viewStub: android.view.ViewStub{420bc4a8 G.E..... ......I. 0,0-0,0 #7f0c0062}
09-27 11:49:39.414 2275-2275/com.owen.provider E/OWEN: layout: null
09-27 11:49:49.044 2275-2275/com.owen.provider E/OWEN: viewStub: android.view.ViewStub{420bc4a8 G.E..... ......I. 0,0-0,0 #7f0c0062}
09-27 11:49:49.044 2275-2275/com.owen.provider E/OWEN: find viewStub: null
加载前布局
加载后布局
public ViewStub(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context);
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.ViewStub, defStyleAttr, defStyleRes);
mInflatedId = a.getResourceId(R.styleable.ViewStub_inflatedId, NO_ID); // 获取InflatedId
mLayoutResource = a.getResourceId(R.styleable.ViewStub_layout, 0); // 获取要加载布局的id
mID = a.getResourceId(R.styleable.ViewStub_id, NO_ID);
a.recycle();
setVisibility(GONE); //设置不可见
setWillNotDraw(true); // 设置不绘制内容
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(0, 0); // 设置布局的宽高都是0
}
//加载布标布局
/**
* Inflates the layout resource identified by {@link #getLayoutResource()}
* and replaces this StubbedView in its parent by the inflated layout resource.
*
* @return The inflated layout resource.
*
*/
public View inflate() {
final ViewParent viewParent = getParent(); // 通过getParent来获取View的父视图
if (viewParent != null && viewParent instanceof ViewGroup) { // 父布局是否存在并且是ViewGroup类型
if (mLayoutResource != 0) {
final ViewGroup parent = (ViewGroup) viewParent; //转成ViewGroup类型
final LayoutInflater factory;
if (mInflater != null) {
factory = mInflater;
} else {
factory = LayoutInflater.from(mContext);
}
// 加载布标Id
final View view = factory.inflate(mLayoutResource, parent,
false);
if (mInflatedId != NO_ID) {
view.setId(mInflatedId); //设置布标布局根布局的Id
}
final int index = parent.indexOfChild(this);
parent.removeViewInLayout(this); //将View stub 布局从根布局中移出
final ViewGroup.LayoutParams layoutParams = getLayoutParams();
if (layoutParams != null) { //判断ViewStub 是否设置了布局参数, 然后将布局添加到父布局中
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");
}
}