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