正确使用ViewStub
最近在使用ViewStub,在使用的過(guò)程中遇到了一些問(wèn)題,所以現(xiàn)在就在這里記錄一下,也免得后面使用的人少走一些坑。事情是這樣的,由于項(xiàng)目中要用ViewStub對(duì)原有的一些布局頁(yè)面進(jìn)行懶加載,提升用戶體驗(yàn),所以簡(jiǎn)單了解了一下ViewStub的用法后,就將原來(lái)的需要懶加載的Layout單獨(dú)設(shè)置為一個(gè)xml文件。本來(lái)以為是沒(méi)有問(wèn)題,但是一看原來(lái)并不是這么簡(jiǎn)單。有好幾個(gè)需要注意的點(diǎn),現(xiàn)在分開(kāi)來(lái)講:
一、ViewStub多次inflate引發(fā)的exception:
ViewStub must have a non-null ViewGroup viewParent 相信第一次用的人應(yīng)該都會(huì)遇到過(guò)這個(gè)的問(wèn)題,我們進(jìn)去inflate()的方法源碼看看,
public View inflate() {
final ViewParent viewParent = getParent(); if (viewParent != null && viewParent instanceof ViewGroup) { if (mLayoutResource != 0) {final ViewGroup parent = (ViewGroup) viewParent;
final LayoutInflater factory;
if (mInflater != null) {
factory = mInflater;
} else {
factory = LayoutInflater.from(mContext);
}
final View view = factory.inflate(mLayoutResource, parent,
false); if (mInflatedId != NO_ID) { view.setId(mInflatedId);
} final int index = parent.indexOfChild(this); parent.removeViewInLayout(this); final ViewGroup.LayoutParams layoutParams = getLayoutParams(); if (layoutParams != null) {
parent.addView(view, index, layoutParams);
} else {
parent.addView(view, index);
} mInflatedViewRef = new WeakReference<View>(view);
if (mInflateListener != null) {
mInflateListener.onInflate(this, view);
} return view; } else {
throw new IllegalArgumentException("ViewStub must have a valid layoutResource");
}
}
是不是很熟悉?由于ViewStub第一次inflate的時(shí)候,就已經(jīng)將需要顯示的布局替換掉自己了,所以第二次inflate的時(shí)候,getParent()是null,所以就會(huì)報(bào)異常。解決方法是inflate()的時(shí)候?qū)iew保存起來(lái),然后下次判斷這個(gè)View是否為NUll,如果是null就inflate().否則就直接使用這個(gè)view,還有一種就是setOnInflateListener,這個(gè)網(wǎng)上也有文章,這里不細(xì)說(shuō)。如果被包含的layout的子View沒(méi)有用戶邏輯操作的,可以使用ViewStub的setVisibility()來(lái)控制顯示和隱藏。里面已經(jīng)做了inflate多次的判斷的了,不會(huì)有異常的。
二、被包含的layout里面設(shè)置layout_margin屬性失效而設(shè)置padding屬性有效的問(wèn)題。這個(gè)問(wèn)題需要看源碼才能解答,所以就看了一下源碼。還是看inflate()方法。
final?ViewGroup.LayoutParams layoutParams = getLayoutParams();
if?(layoutParams !=?null) {
parent.addView(view, index, layoutParams);
}?else?{
parent.addView(view, index);
}
看到這一段代碼了嗎?有個(gè)getLayoutParams() 以及 parent.addView方法。可以看到,getlayoutParams獲取的是VeiwStub的LayoutParams,而不是被顯示的Layout_params。所以,addView的時(shí)候,要么就是將ViewStub的layoutParams賦值給將要顯示的view,要么直接調(diào)用addView(view,index),所以如果想要margin有效果,我們之能將layout_margin放到ViewStub里面,同理,如果是在相對(duì)布局里面,below_? above_這些屬性控制都要放到viewStub那里,而不是放到將要顯示的layout里面。那為什么padding會(huì)在將要顯示的layout中起作用呢?這就要好好理解一下ViewGroup.LayoutParams layoutParams了,你會(huì)發(fā)現(xiàn)padding并不屬于ViewGroup.LayoutParams layoutParams里面的,而是屬于View的成員變量,這也就解釋了為什么padding屬性不會(huì)失效了,之前還以為padding設(shè)置ViewGroup.LayoutParams里面設(shè)置的呢。好了,這里相信大家對(duì)ViewStub都有一個(gè)很清晰的了解了,有什么問(wèn)題,可以相互交流哦,如何比較優(yōu)雅的使用ViewStub呢?經(jīng)過(guò)本人試驗(yàn),個(gè)人還是比較推薦使用setOnInflateListener,因?yàn)樗粫?huì)被調(diào)用一次,就是剛inflate的時(shí)候,而且無(wú)論無(wú)論inflate的layout中是不是有其它的事件監(jiān)聽(tīng),它都可以實(shí)現(xiàn)。
我建了個(gè)qq群:207678498
總結(jié)
以上是生活随笔為你收集整理的正确使用ViewStub的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 线性代数第3章思维导图
- 下一篇: 【BZOJ3514】Codechef M