正确使用ViewStub
最近在使用ViewStub,在使用的過程中遇到了一些問題,所以現在就在這里記錄一下,也免得后面使用的人少走一些坑。事情是這樣的,由于項目中要用ViewStub對原有的一些布局頁面進行懶加載,提升用戶體驗,所以簡單了解了一下ViewStub的用法后,就將原來的需要懶加載的Layout單獨設置為一個xml文件。本來以為是沒有問題,但是一看原來并不是這么簡單。有好幾個需要注意的點,現在分開來講:
一、ViewStub多次inflate引發的exception:
ViewStub must have a non-null ViewGroup viewParent 相信第一次用的人應該都會遇到過這個的問題,我們進去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的時候,就已經將需要顯示的布局替換掉自己了,所以第二次inflate的時候,getParent()是null,所以就會報異常。解決方法是inflate()的時候將view保存起來,然后下次判斷這個View是否為NUll,如果是null就inflate().否則就直接使用這個view,還有一種就是setOnInflateListener,這個網上也有文章,這里不細說。如果被包含的layout的子View沒有用戶邏輯操作的,可以使用ViewStub的setVisibility()來控制顯示和隱藏。里面已經做了inflate多次的判斷的了,不會有異常的。
二、被包含的layout里面設置layout_margin屬性失效而設置padding屬性有效的問題。這個問題需要看源碼才能解答,所以就看了一下源碼。還是看inflate()方法。
final?ViewGroup.LayoutParams layoutParams = getLayoutParams();
if?(layoutParams !=?null) {
parent.addView(view, index, layoutParams);
}?else?{
parent.addView(view, index);
}
看到這一段代碼了嗎?有個getLayoutParams() 以及 parent.addView方法??梢钥吹?#xff0c;getlayoutParams獲取的是VeiwStub的LayoutParams,而不是被顯示的Layout_params。所以,addView的時候,要么就是將ViewStub的layoutParams賦值給將要顯示的view,要么直接調用addView(view,index),所以如果想要margin有效果,我們之能將layout_margin放到ViewStub里面,同理,如果是在相對布局里面,below_? above_這些屬性控制都要放到viewStub那里,而不是放到將要顯示的layout里面。那為什么padding會在將要顯示的layout中起作用呢?這就要好好理解一下ViewGroup.LayoutParams layoutParams了,你會發現padding并不屬于ViewGroup.LayoutParams layoutParams里面的,而是屬于View的成員變量,這也就解釋了為什么padding屬性不會失效了,之前還以為padding設置ViewGroup.LayoutParams里面設置的呢。好了,這里相信大家對ViewStub都有一個很清晰的了解了,有什么問題,可以相互交流哦,如何比較優雅的使用ViewStub呢?經過本人試驗,個人還是比較推薦使用setOnInflateListener,因為它只會被調用一次,就是剛inflate的時候,而且無論無論inflate的layout中是不是有其它的事件監聽,它都可以實現。
我建了個qq群:207678498
總結
以上是生活随笔為你收集整理的正确使用ViewStub的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 线性代数第3章思维导图
- 下一篇: 【BZOJ3514】Codechef M