Android:ListView.addHeaderView()用法及其注意事項

奮鬥年輕人發表於2016-11-23

在程式碼中使用 listView.addHeaderView(…) 方法可以在ListView元件上方新增上其他元件,並且連結在一起像是一個新元件。如果多次使用 .addHeaderView(…) ,則最先新增的元件在最上方,按新增的先後順序由上到下羅列。 
此時listView 的 position = 0 的位置對應的是view1,而不再是原來listView中的第一條了。如下圖所示: 
這裡寫圖片描述

該方法幫我們解決了佈局複雜的多佈局麻煩,例如美團的listView頂部的複雜多佈局實現:

這裡寫圖片描述這裡寫圖片描述

另外,若要對做原來的ListView做不可見設定,可使用將listView的adapter中資料置空的方法,在可見時再還原資料。

二、addHeaderView和setAdapter的順序問題:

特別注意:在呼叫addHeaderView和setAdapter的順序上,有時候會報這樣的一個異常:

java.lang.IllegalStateException: 
Cannot add header view to list --setAdapter has already been called.
  • 1
  • 2
  • 1
  • 2

產生原因:addHeaderView()呼叫在setAdapter()之後,並且該程式碼執行在Android4.3之前的系統版本。就是因為我們在addHeaderView之前呼叫了setAdapter。

三、注意事項:

1,焦點之爭:

item內如果有button等控制元件時,在監聽listview的onitemclick事件時,焦點會被item內的button、imagebutton等控制元件搶走,從而導致在listview設定了onitemclick事件後不會被觸發。解決方法是在初始化item的時候遮蔽掉其內部button等控制元件的焦點獲取,具體方法可以在自定義item的根控制元件中呼叫:

setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
  • 1
  • 1

這樣就能阻塞字控制元件搶奪焦點,listview的onitemclick就能被正確觸發,同時對item內部的button等控制元件也沒有影響,他們在被點選時照樣可以觸發自身的點選事件。

2、過載方法:

當listview需要新增headerview時,可以通過呼叫listview的addHeaderView(headView, null, false) 方法,該方法還有一個過載方法 addHeaderView(headView);這兩個方法的區別是前一個方法可以控制header是否可以被 selected,如果不想被selected則將第三個引數設定成false;

3、順序問題詳解:

接著上面說的新增header,新增header時呼叫的addHeaderView方法必須放在listview.setadapter前面,意思很明 確就是如果想給listview新增頭部則必須在給其繫結adapter前新增,否則會報錯。原因是當我們在呼叫setAdapter方法時會 Android會判斷當前listview是否已經新增header,如果已經新增則會生成一個新的tempadapter,這個新的 tempadapter包含我們設定的adapter所有內容以及listview的header和footer。所以當我們在給listview新增了 header後在程式中呼叫listview.getadapter時返回的是tempadapter而不是我們通過setadapter傳進去的 adapter。如果沒有設定adapter則tempadapter與我們自己的adapter是一樣的。listview.getadapter().getcount()方法返回值會比我們預期的要大,原因是新增了header。

4、位置問題:

接著上面的tempadapter說,我們自定義adapter裡面的getitem方法裡面返回的position是不包括header的,是我們自定義adapter中資料position編號從0開始,也就是說與我們傳進去的list的位置是一樣的。 
而listview的onitemclick方法中:

public void onItemClick(AdapterView
  • 1
  • 1

headView和footerView都可以響應onItemClick方法,headView的position為0,footerView的position最大。 
不過可以給headView和footerView設定OnClickListener來覆蓋OnItemClick,這樣,你點選headview或者footerView將觸發OnClickListener而不是onItemClick(). 
在使用ListView.addHeaderView(),牽涉到佈局管理問題,往往還會遇到型別轉換異常: 
《java.lang.ClassCastException:android.widget.LinearLayoutLayoutParamscannotbecasttoandroid.widget.AbsListViewLayoutParams》

其中本文中部分文字參考:http://892848153.iteye.com/blog/1923680,謝謝大神賜教!

相關文章