Android ListView的OnItemClickListener詳解
我們?cè)谑褂肔istView的時(shí)候,一般都會(huì)為L(zhǎng)istView添加一個(gè)響應(yīng)事件android.widget.AdapterView.OnItemClickListener。本文主要在于對(duì)OnItemClickListener的position和id參數(shù)做詳細(xì)的解釋,我相信有些人在這上面走了些彎路。
先來(lái)看一下官方的文檔
position The position of the view in the adapter.
id The row id of the item that was clicked.
而這兩行字并沒(méi)有解釋清楚position和id的區(qū)別。另外,我們還有個(gè)Adapter的getView方法。
public abstract View getView (int position, View convertView, ViewGroup parent)
這里也有一個(gè)position。
初步接觸ListView的同學(xué),一般會(huì)直接繼承ArrayAdapter,然后(比如我),就想當(dāng)然的認(rèn)為OnItemClick的position和getView的position是一樣的啊。于是我們就getItem(position)來(lái)獲取相應(yīng)的數(shù)據(jù)。
那么這段代碼有沒(méi)有錯(cuò)呢?如果有錯(cuò)的話,在什么情況會(huì)出錯(cuò)呢?
第一個(gè)問(wèn)題的答案是,當(dāng)我們?yōu)長(zhǎng)istView添加headerView或者footerView之后,這段代碼就不一定是我們想要的了。
出現(xiàn)問(wèn)題的原因在于,當(dāng)我們?yōu)長(zhǎng)istView添加headerView或者footerView之后,ListView在setAdapter時(shí),做了一些事情,這導(dǎo)致,Adapter和OnItemClickListener中的position含義發(fā)生了變化。
我們可以來(lái)看看ListView中setAdapter的實(shí)現(xiàn)
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
resetList();
mRecycler.clear();
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
可以看出,如果這個(gè)ListView存在headerView或者footerView的話,那么會(huì)在我們傳入的adapter外面在封裝一層HeaderViewListAdapter,這是一個(gè)專門用來(lái)自動(dòng)處理headerView和footerView的adapter。在ListView中,本身不區(qū)分headerView,footerView。ListView可以理解成是只負(fù)責(zé)管理一組View的數(shù)組的UI(ViewGroup),headerView和footerView都委托給HeaderViewListAdapter來(lái)處理。(從這里也可以看到為什么API文檔中提到,addFooterView和addHeaderView要在setAdapter函數(shù)之前調(diào)用,如果在之后調(diào)用,那么就不會(huì)生成HeaderViewListAdapter,從而導(dǎo)致顯示不出headerView和footerView)。
回到開頭的問(wèn)題,position和id有啥區(qū)別。為此,我們找一下position和id是怎么傳進(jìn)來(lái)的。
OnItemClickListener在android.widget.AdapterView的public boolean performItemClick(View view, int position, long id)函數(shù)中被調(diào)用。
performItemClick在android.widget.AbsListView.PerformClick.run() 中被調(diào)用
private class PerformClick extends WindowRunnnable implements Runnable {
int mClickMotionPosition;
public void run() {
// The data has changed since we posted this action in the event queue,
// bail out before bad things happen
if (mDataChanged) return;
final ListAdapter adapter = mAdapter;
final int motionPosition = mClickMotionPosition;
if (adapter != null && mItemCount > 0 &&
motionPosition != INVALID_<strong>POSITION</strong> &&
motionPosition < adapter.getCount() && sameWindow()) {
final View view = getChildAt(motionPosition - mFirstPosition);
// If there is no view, something bad happened (the view scrolled off the
// screen, etc.) and we should cancel the click
if (view != null) {
performItemClick(view, motionPosition, adapter.getItemId(motionPosition));
}
}
}
}
可以看到,position事實(shí)上就是ListView中被點(diǎn)擊的view的位置。注意,在ListView中是不負(fù)責(zé)處理headerView和footViewer的,所以,這個(gè)位置應(yīng)該是這個(gè)被點(diǎn)擊的view在數(shù)組[所有的headerView,用戶添加的view,所有的footerView]中的位置(請(qǐng)自行參考HeaderViewListAdapter的getView實(shí)現(xiàn))。而id是來(lái)自于adapter.getItemId(position)。
對(duì)于ArrayAdapter的getItemId函數(shù),實(shí)現(xiàn)就是return position。id和position是一致的。
然而,對(duì)于HeaderViewListAdapter
public long getItemId(int <strong>position</strong>) {
int numHeaders = getHeadersCount();
if (mAdapter != null && <strong>position</strong> >= numHeaders) {
int adjPosition = <strong>position</strong> - numHeaders;
int adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getItemId(adjPosition);
}
}
return -1;
}
實(shí)現(xiàn)邏輯是,如果position指向了headerView或footerView,那么返回-1,否則,將返回在用戶view數(shù)組的位置。
也就是說(shuō)
id=position-headerView的個(gè)數(shù)(id < headerviewer的個(gè)數(shù)+用戶view的個(gè)數(shù)),否則=-1
因此,OnItemClickListener的正確實(shí)現(xiàn)如下:
void onItemClick(AdapterViewparent, View view, int <strong>position</strong>, long id){
if(id == -1) {
// 點(diǎn)擊的是headerView或者<strong>footerView</strong>
return;
}
int realPosition=(int)id;
T item=getItem(realPosition);
// 響應(yīng)代碼
}
相關(guān)閱讀:
Android 中ListView setOnItemClickListener點(diǎn)擊無(wú)效原因分析
以上所述是小編給大家介紹的Android ListView的OnItemClickListener詳解,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Android ListView的item中嵌套ScrollView的解決辦法
- Android中Listview點(diǎn)擊item不變顏色及設(shè)置listselector 無(wú)效的解決方案
- Android 中ListView的Item點(diǎn)擊事件失效的快速解決方法
- Android使用ListView批量刪除item的方法
- Android實(shí)現(xiàn)帶有邊框的ListView和item的方法
- Android 中ListView setOnItemClickListener點(diǎn)擊無(wú)效原因分析
- Android中ListView Item布局優(yōu)化技巧
- Android開發(fā)之ListView實(shí)現(xiàn)Item局部刷新
- Android ListView的item背景色設(shè)置和item點(diǎn)擊無(wú)響應(yīng)的解決方法
- Android中ListView的item點(diǎn)擊沒(méi)有反應(yīng)的解決方法
相關(guān)文章
Android實(shí)現(xiàn)從底部彈出的Dialog示例(一)
這篇文章主要介紹了Android實(shí)現(xiàn)從底部彈出的Dialog示例(一),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-01-01
Android Jetpack系列之App Startup使用詳解
這篇文章主要為大家介紹了Android Jetpack系列之App Startup使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
通過(guò)實(shí)例簡(jiǎn)單講解Android App中的Activity組件
這篇文章主要介紹了通過(guò)Android App中的Activity組件,包括Activity的定義和繼承以及啟動(dòng)等基本知識(shí),需要的朋友可以參考下2016-04-04
Android Studio preview 不固定及常見問(wèn)題的解決辦法
preview 可以幫助您預(yù)覽您的布局文件將如何在用戶的設(shè)備上呈現(xiàn)。這篇文章主要介紹了Android Studio preview 不固定及常見問(wèn)題的解決辦法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-05-05
Android使用Notification實(shí)現(xiàn)通知功能
這篇文章主要為大家詳細(xì)介紹了Android使用Notification實(shí)現(xiàn)通知功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
Android EditText長(zhǎng)按菜單中分享功能的隱藏方法
Android EditText控件是經(jīng)常使用的控件,下面這篇文章主要給大家介紹了關(guān)于Android中EditText長(zhǎng)按菜單中分享功能的隱藏方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02
Android EditText限制輸入字?jǐn)?shù)的方法
這篇文章主要介紹了Android EditText限制輸入字?jǐn)?shù)的方法,涉及Android針對(duì)EditText文本與字符串操作相關(guān)技巧,需要的朋友可以參考下2016-01-01
Android ViewPager導(dǎo)航小圓點(diǎn)實(shí)現(xiàn)無(wú)限循環(huán)效果
這篇文章主要為大家詳細(xì)介紹了Android ViewPager導(dǎo)航小圓點(diǎn)實(shí)現(xiàn)無(wú)限循環(huán)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08

