接著上次的問(wèn)題,已介紹過(guò),在初始化或說(shuō)OnCreate方法中獲得加載的布局的寬高,最后說(shuō)到,調(diào)用view.measure(0, 0);然后在調(diào)用getMeasuredWidth和getMeasuredHeight就能夠取得丈量的寬高。可以參考:Android如何在初始化的時(shí)候獲得加載的布局的寬高
今天在寫(xiě)類(lèi)似的效果時(shí),給ListView加載1個(gè)頭部視圖,通過(guò)listView$addHeadView添加到ListView的頭部。為了描寫(xiě)起來(lái)簡(jiǎn)單起見(jiàn),這個(gè)頭部視圖的布局我做了簡(jiǎn)化為下面:headview.xml
然后在初始化的時(shí)候想獲得該布局的寬高,就這樣做了:
結(jié)果。。。。。
程序崩潰了!尼瑪,不是說(shuō)好的headView.measure(0, 0);調(diào)用完就可以獲得到布局的寬高了嘛,怎樣這句好報(bào)錯(cuò)空指針異常了?
然后把布局修改成線性布局
居然就行了。。。
也獲得到了丈量的寬高:
接下來(lái)又開(kāi)始了對(duì)問(wèn)題的研究。為了簡(jiǎn)化問(wèn)題,還是依照上次的此路。在上次的基礎(chǔ)上添加布局viewgroup_relativelayout.xml,其實(shí)就是將外層的LinearLayout修改成RelativeLayout了,其他地方未變。加載該布局,然后丈量寬高。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <View android:layout_width="50dp" android:layout_height="50dp" /> </RelativeLayout>
看結(jié)果:
View,textview和線性布局的ViewGroup和上次的結(jié)果1樣。但是將相對(duì)布局的ViewGroup直接掛掉。。剛開(kāi)始還是特別的不爽的,為何常常遇到問(wèn)題,不過(guò)1想,解決問(wèn)題的進(jìn)程就是水平提高的進(jìn)程,所以打起精神進(jìn)行研究。嘿嘿~
通過(guò)比較發(fā)現(xiàn)RelativeLayout出錯(cuò)了,所以很容易將空指針異常的地方定位在RelativeLayout的onMeasure函數(shù)中。
但是這個(gè)函數(shù)比較復(fù)雜了。兩百多行代碼,里面牽扯了很多的域變量和函數(shù),讀起來(lái)挺累的。因此在網(wǎng)上搜了好久,在eoe上面看到有人說(shuō)了下面的方法:
如果使用Inflater的情況下會(huì)出現(xiàn)以上毛病,緣由是用Inflater渲染組件的時(shí)候并沒(méi)有給其指定父控件,所以渲染器不會(huì)去解析width 和 height屬性,就會(huì)致使空指針異常。
解決方法:
view.setLayoutParams(newLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));指定寬度和高度,然后調(diào)用measure方法就OK。
其實(shí)這個(gè)說(shuō)法前面就研究過(guò),確切是這模樣的,但是LinearLayout為何沒(méi)出問(wèn)題RelativeLayout就出問(wèn)題了呢,所以還是沒(méi)有說(shuō)明白緣由在哪里。
我嘗試了1下確切弄定了,緣由尚不清楚,那就肯定需要查源代碼了。在這個(gè)指點(diǎn)下給我提供了方向就是極可能在onMeasure方法里面調(diào)用了該相對(duì)布局的參數(shù)mLayoutParams,由于本來(lái)為null,那末調(diào)用的話就會(huì)報(bào)告空指針異常!
接下來(lái)就在源碼的onMeasure函數(shù)里面將所有出現(xiàn)mLayoutParams的地方打上斷點(diǎn)。然后斷點(diǎn)調(diào)試
RelativeLayou類(lèi)(我查看的是4.2的源碼)
果然mLayoutParams變量不存在為null。
到現(xiàn)在為止問(wèn)題就清楚了。由于調(diào)用headView.measure(0, 0);的時(shí)候是通過(guò)inflate(R.layout.headview, null);方式加載的布局,因此設(shè)置的外層RelativeLayout布局的LayoutParams是null的,恰巧相對(duì)布局沒(méi)有檢查是不是為null就直接調(diào)用了mLayoutParams.width或mLayoutParams.height,因此就報(bào)空指針毛病了。這多是1個(gè)bug吧我認(rèn)為。
既然知道了問(wèn)題是出在了這里了,那末也很容易解決了。
最少有以下的解決方法:
1,加載布局的時(shí)候通過(guò)inflater.inflate(R.layout.viewgroup_relativelayout,(ViewGroup) findViewById(R.id.mainLayout),false);方式加載。這樣的話會(huì)設(shè)置他的布局參數(shù)。
2 手動(dòng)設(shè)置布局參數(shù)添加上
現(xiàn)在再來(lái)看上1篇博客里面講的這個(gè)方法:
看起來(lái)貌似就是為了不外層布局是RelativeLayout的情況對(duì)LayoutParams做了判斷!但是直接調(diào)用上面這個(gè)方法依然不行,由于new出來(lái)的LayoutParams沒(méi)有設(shè)置進(jìn)去,所以還需要調(diào)用child.setLayoutParams(lp);然后就弄定了。經(jīng)過(guò)測(cè)試ok!
回到博客開(kāi)始在ListView添加頭View所遇到的問(wèn)題也就很容易解決了。
1,將相對(duì)布局換成線性布局。
2,依然使用相對(duì)布局,使用上面說(shuō)的兩種方法設(shè)置外層的相對(duì)布局的布局參數(shù)。比如使用下面的方法,在家在布局的時(shí)候帶上父布局,結(jié)果弄定!好開(kāi)心
將headView.measure(0, 0);換成measureView (headView);也能夠的。
但是加載布局的時(shí)候不帶上父布局,調(diào)用的是headView =inflater.inflate(R.layout.headview, null);即便用下面代碼:
程序居然又崩潰了。看調(diào)試結(jié)果:
不過(guò)不用擔(dān)心,這時(shí)候的毛病不是空指針了,而是類(lèi)轉(zhuǎn)換異常,相信通錯(cuò)誤誤很容易修改了
lp= new AbsListView.LayoutParams(AbsListView.LayoutParams.FILL_PARENT,AbsListView.LayoutParams.WRAP_CONTENT);
然后在運(yùn)行就行了,大功告成。最后的忠告就是需要自己需要丈量布局寬高的時(shí)候慎用RelativeLayout,猶如解決ScrollView和ListView沖突的時(shí)候1種解決方法,這里我們只討論其中1個(gè)沖突就是:致使ListView的高度顯示不完全,出現(xiàn)只顯示部份內(nèi)容的情況。解決方法就是就是丈量ListView的總高度,然后設(shè)置1下,關(guān)鍵代碼以下。試想,如果這時(shí)候候如果各個(gè)item是RelativeLayout的話,肯定會(huì)出錯(cuò)。
最后,這些東西可能有些人寫(xiě)程序的時(shí)候都從沒(méi)遇到過(guò),固然也不影響寫(xiě)出漂亮的APP。但是我認(rèn)為不論是甚么問(wèn)題,都能鍛煉解決問(wèn)題的能力,都是有助于學(xué)習(xí)。
文字表達(dá)能力太差,表述能力是硬傷啊!
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
上一篇 仿網(wǎng)易彩票思路