android stub,Android:ViewStub
ViewStub是一個輕量級View,它是一個看不見的,并且不占布局位置,占用資源非常小的視圖對象。可以為ViewStub指定一個布局,加載布局時,只有ViewStub會被初始化,然后當(dāng)ViewStub被設(shè)置為可見時,或者是調(diào)用了ViewStub.inflate()時,ViewStub所指向的布局會被加載和實例化,然后ViewStub的布局屬性都會傳給它指向的布局。這樣就可以使用ViewStub來設(shè)置是否顯示某個布局。
android:inflatedId="@+id/inflatedId"
android:id="@+id/viewStub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout="@layout/layout_inflate_view_stub"/>
ViewStub是繼承自View,設(shè)置它的可見性,可以通過ViewStub#setVisibility()和ViewStub#inflate()。
先看ViewStub#setVisibility()方法。
private WeakReference mInflatedViewRef;
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();
}
}
}
初次調(diào)用該方法,mInflatedViewRef=null。因此會先走else邏輯。先通過super.setVisibility()調(diào)用View的setVisibility方法,更改相關(guān)的標志。然后無論設(shè)置的是View.VISIBLE或者是View.INVISIBLE都會去調(diào)用ViewStub#inflate()方法。如果mInflatedViewRef!=null,就是正常的設(shè)置可見性。
再看View#inflate()方法。在xml布局中ViewStub節(jié)點下android:layout引入的布局會將ViewStub替換掉,并且ViewStub的寬高等屬性會被該布局使用。
public View inflate() {
final ViewParent viewParent = getParent();
if (viewParent != null && viewParent instanceof ViewGroup) {
if (mLayoutResource != 0) {
final ViewGroup parent = (ViewGroup) viewParent;
/*
inflateViewNoAdd()方法被填充的布局生成View對象。如果為ViewStub設(shè)置了屬性inflatedId,那么這里的view的id會被替換成該inflatedId。
*/
final View view = inflateViewNoAdd(parent);
//將ViewStub替換成被填充的布局,并使用了ViewStub的屬性。
replaceSelfWithView(view, parent);
mInflatedViewRef = new WeakReference<>(view);
if (mInflateListener != null) {
//監(jiān)聽事件需要在inflate()或者setVisibility()之前調(diào)用。
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");
}
}
最后說一下id相關(guān)。
android:inflatedId="@+id/inflatedId"
android:id="@+id/viewStub"
... />
這里定義了id和inflatedId。id是通過findViewById來獲取ViewStub的。inflatedId則是獲取被填充的布局,前提是調(diào)用了ViewStub#setVisibility()或者ViewStub#inflate()方法。inflatedId是在方法inflateViewNoAdd()中設(shè)置給被填充的布局的。
使用ViewStub需要注意的地方。
ViewStub只能加載一次。這個可以從方法replaceSelfWithView看出來。因此ViewStub不適合需要按需隱藏的情況。
private void replaceSelfWithView(View view, ViewGroup parent) {
final int index = parent.indexOfChild(this);
//移除ViewStub
parent.removeViewInLayout(this);
final ViewGroup.LayoutParams layoutParams = getLayoutParams();
//添加被填充的布局
if (layoutParams != null) {
parent.addView(view, index, layoutParams);
} else {
parent.addView(view, index);
}
}
ViewStub不能嵌套merge標簽
一般使用場景。
程序運行期間,某個布局在加載后,就不會有變化,除非銷毀該頁面再重新加載。
想要控制顯示與隱藏的是一個布局文件,而非某個view。
總結(jié)
以上是生活随笔為你收集整理的android stub,Android:ViewStub的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 写了cookie阻止通过输入地址直接访问
- 下一篇: 辅助同步器