Android ListView的OnItemClickListener详解

 更新时间:2016年07月28日 11:12:22   作者:wula0010  
这篇文章主要介绍了Android ListView的OnItemClickListener详解的相关资料,涉及到OnItemClickListener的position和id参数做详细的解释的知识点,非常不错,具有参考借鉴价值,需要的朋友参考下

我们在使用ListView的时候,一般都会为ListView添加一个响应事件android.widget.AdapterView.OnItemClickListener。本文主要在于对OnItemClickListener的position和id参数做详细的解释,我相信有些人在这上面走了些弯路。

先来看一下官方的文档

position The position of the view in the adapter.

id The row id of the item that was clicked.

而这两行字并没有解释清楚position和id的区别。另外,我们还有个Adapter的getView方法。
public abstract View getView (int position, View convertView, ViewGroup parent)
这里也有一个position。

初步接触ListView的同学,一般会直接继承ArrayAdapter,然后(比如我),就想当然的认为OnItemClick的position和getView的position是一样的啊。于是我们就getItem(position)来获取相应的数据。

那么这段代码有没有错呢?如果有错的话,在什么情况会出错呢?

第一个问题的答案是,当我们为ListView添加headerView或者footerView之后,这段代码就不一定是我们想要的了。
出现问题的原因在于,当我们为ListView添加headerView或者footerView之后,ListView在setAdapter时,做了一些事情,这导致,Adapter和OnItemClickListener中的position含义发生了变化。

我们可以来看看ListView中setAdapter的实现

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; 
} 

可以看出,如果这个ListView存在headerView或者footerView的话,那么会在我们传入的adapter外面在封装一层HeaderViewListAdapter,这是一个专门用来自动处理headerView和footerView的adapter。在ListView中,本身不区分headerView,footerView。ListView可以理解成是只负责管理一组View的数组的UI(ViewGroup),headerView和footerView都委托给HeaderViewListAdapter来处理。(从这里也可以看到为什么API文档中提到,addFooterView和addHeaderView要在setAdapter函数之前调用,如果在之后调用,那么就不会生成HeaderViewListAdapter,从而导致显示不出headerView和footerView)。

回到开头的问题,position和id有啥区别。为此,我们找一下position和id是怎么传进来的。

OnItemClickListener在android.widget.AdapterView的public boolean performItemClick(View view, int position, long id)函数中被调用。

performItemClick在android.widget.AbsListView.PerformClick.run() 中被调用

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事实上就是ListView中被点击的view的位置。注意,在ListView中是不负责处理headerView和footViewer的,所以,这个位置应该是这个被点击的view在数组[所有的headerView,用户添加的view,所有的footerView]中的位置(请自行参考HeaderViewListAdapter的getView实现)。而id是来自于adapter.getItemId(position)。
对于ArrayAdapter的getItemId函数,实现就是return position。id和position是一致的。

然而,对于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; 
} 

实现逻辑是,如果position指向了headerView或footerView,那么返回-1,否则,将返回在用户view数组的位置。
也就是说

id=position-headerView的个数(id < headerviewer的个数+用户view的个数),否则=-1

因此,OnItemClickListener的正确实现如下:

void onItemClick(AdapterViewparent, View view, int <strong>position</strong>, long id){ 
if(id == -1) { 
// 点击的是headerView或者<strong>footerView</strong> 
return; 
} 
int realPosition=(int)id; 
T item=getItem(realPosition); 
// 响应代码 
}

相关阅读:

Android 中ListView setOnItemClickListener点击无效原因分析

以上所述是小编给大家介绍的Android ListView的OnItemClickListener详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • Android实现从底部弹出的Dialog示例(一)

    Android实现从底部弹出的Dialog示例(一)

    这篇文章主要介绍了Android实现从底部弹出的Dialog示例(一),具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-01-01
  • Flutter SystemChrome使用方法详解

    Flutter SystemChrome使用方法详解

    这篇文章主要为大家介绍了Flutter SystemChrome使用方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • Android Jetpack系列之App Startup使用详解

    Android Jetpack系列之App Startup使用详解

    这篇文章主要为大家介绍了Android Jetpack系列之App Startup使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • Android工程师面试题大全

    Android工程师面试题大全

    这篇文章主要为大家分享了Android工程师面试题,内容很丰富,结合网上各位的大神秒下的面试题做个总结,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • 通过实例简单讲解Android App中的Activity组件

    通过实例简单讲解Android App中的Activity组件

    这篇文章主要介绍了通过Android App中的Activity组件,包括Activity的定义和继承以及启动等基本知识,需要的朋友可以参考下
    2016-04-04
  • Android Studio preview 不固定及常见问题的解决办法

    Android Studio preview 不固定及常见问题的解决办法

    preview 可以帮助您预览您的布局文件将如何在用户的设备上呈现。这篇文章主要介绍了Android Studio preview 不固定及常见问题的解决办法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • Android使用Notification实现通知功能

    Android使用Notification实现通知功能

    这篇文章主要为大家详细介绍了Android使用Notification实现通知功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • Android EditText长按菜单中分享功能的隐藏方法

    Android EditText长按菜单中分享功能的隐藏方法

    Android EditText控件是经常使用的控件,下面这篇文章主要给大家介绍了关于Android中EditText长按菜单中分享功能的隐藏方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-02-02
  • Android EditText限制输入字数的方法

    Android EditText限制输入字数的方法

    这篇文章主要介绍了Android EditText限制输入字数的方法,涉及Android针对EditText文本与字符串操作相关技巧,需要的朋友可以参考下
    2016-01-01
  • Android ViewPager导航小圆点实现无限循环效果

    Android ViewPager导航小圆点实现无限循环效果

    这篇文章主要为大家详细介绍了Android ViewPager导航小圆点实现无限循环效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08

最新评论