- 浏览: 84093 次
- 性别:
- 来自: 北京
文章分类
最新评论
我们在使用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的实现
437 public void setAdapter(ListAdapter adapter) {
438 if (mAdapter != null && mDataSetObserver != null) {
439 mAdapter.unregisterDataSetObserver(mDataSetObserver);
440 }
442 resetList();
443 mRecycler.clear();
445 if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
446 mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
447 } else {
448 mAdapter = adapter;
449 }
可以看出,如果这个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() 中被调用
2497 private class PerformClick extends WindowRunnnable implements Runnable {
2498 int mClickMotionPosition;
2500 public void run() {
2501 // The data has changed since we posted this action in the event queue,
2502 // bail out before bad things happen
2503 if (mDataChanged) return;
2505 final ListAdapter adapter = mAdapter;
2506 final int motionPosition = mClickMotionPosition;
2507 if (adapter != null && mItemCount > 0 &&
2508 motionPosition != INVALID_POSITION &&
2509 motionPosition < adapter.getCount() && sameWindow()) {
2510 final View view = getChildAt(motionPosition - mFirstPosition);
2511 // If there is no view, something bad happened (the view scrolled off the
2512 // screen, etc.) and we should cancel the click
2513 if (view != null) {
2514 performItemClick(view, motionPosition, adapter.getItemId(motionPosition));
2515 }
2516 }
2517 }
2518 }
可以看到,position事实上就是ListView中被点击的view的位置。注意,在ListView中是不负责处理headerView和footViewer的,所以,这个位置应该是这个被点击的view在数组[所有的headerView,用户添加的view,所有的footerView]中的位置(请自行参考HeaderViewListAdapter的getView实现)。而id是来自于adapter.getItemId(position)。
对于ArrayAdapter的getItemId函数,实现就是return position。id和position是一致的。
然而,对于HeaderViewListAdapter
188 public long getItemId(int position) {
189 int numHeaders = getHeadersCount();
190 if (mAdapter != null && position >= numHeaders) {
191 int adjPosition = position - numHeaders;
192 int adapterCount = mAdapter.getCount();
193 if (adjPosition < adapterCount) {
194 return mAdapter.getItemId(adjPosition);
195 }
196 }
197 return -1;
198 }
实现逻辑是,如果position指向了headerView或footerView,那么返回-1,否则,将返回在用户view数组的位置。
也就是说
id=position-headerView的个数(id < headerviewer的个数+用户view的个数),否则=-1
因此,OnItemClickListener的正确实现如下:
1
void onItemClick(AdapterViewparent, View view, int position, long id){
2
if(id<-1) {
3
// 点击的是headerView或者footerView
4
return;
5
}
6
int realPosition=(int)id;
7
T item=getItem(realPosition);
8
// 响应代码
9
}
原文地址:http://blog.iamzsx.me/show.html?id=147001
先来看一下官方的文档
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的实现
437 public void setAdapter(ListAdapter adapter) {
438 if (mAdapter != null && mDataSetObserver != null) {
439 mAdapter.unregisterDataSetObserver(mDataSetObserver);
440 }
442 resetList();
443 mRecycler.clear();
445 if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
446 mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
447 } else {
448 mAdapter = adapter;
449 }
可以看出,如果这个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() 中被调用
2497 private class PerformClick extends WindowRunnnable implements Runnable {
2498 int mClickMotionPosition;
2500 public void run() {
2501 // The data has changed since we posted this action in the event queue,
2502 // bail out before bad things happen
2503 if (mDataChanged) return;
2505 final ListAdapter adapter = mAdapter;
2506 final int motionPosition = mClickMotionPosition;
2507 if (adapter != null && mItemCount > 0 &&
2508 motionPosition != INVALID_POSITION &&
2509 motionPosition < adapter.getCount() && sameWindow()) {
2510 final View view = getChildAt(motionPosition - mFirstPosition);
2511 // If there is no view, something bad happened (the view scrolled off the
2512 // screen, etc.) and we should cancel the click
2513 if (view != null) {
2514 performItemClick(view, motionPosition, adapter.getItemId(motionPosition));
2515 }
2516 }
2517 }
2518 }
可以看到,position事实上就是ListView中被点击的view的位置。注意,在ListView中是不负责处理headerView和footViewer的,所以,这个位置应该是这个被点击的view在数组[所有的headerView,用户添加的view,所有的footerView]中的位置(请自行参考HeaderViewListAdapter的getView实现)。而id是来自于adapter.getItemId(position)。
对于ArrayAdapter的getItemId函数,实现就是return position。id和position是一致的。
然而,对于HeaderViewListAdapter
188 public long getItemId(int position) {
189 int numHeaders = getHeadersCount();
190 if (mAdapter != null && position >= numHeaders) {
191 int adjPosition = position - numHeaders;
192 int adapterCount = mAdapter.getCount();
193 if (adjPosition < adapterCount) {
194 return mAdapter.getItemId(adjPosition);
195 }
196 }
197 return -1;
198 }
实现逻辑是,如果position指向了headerView或footerView,那么返回-1,否则,将返回在用户view数组的位置。
也就是说
id=position-headerView的个数(id < headerviewer的个数+用户view的个数),否则=-1
因此,OnItemClickListener的正确实现如下:
1
void onItemClick(AdapterViewparent, View view, int position, long id){
2
if(id<-1) {
3
// 点击的是headerView或者footerView
4
return;
5
}
6
int realPosition=(int)id;
7
T item=getItem(realPosition);
8
// 响应代码
9
}
原文地址:http://blog.iamzsx.me/show.html?id=147001
发表评论
-
Android SDK下载速度慢无法更新?使用国内镜像站加速
2016-01-29 18:18 722https://blog.kuoruan.com/24.htm ... -
探秘腾讯Android手机游戏平台之不安装游戏APK直接启动法
2014-08-01 12:02 396原文地址:http://blog.zhourunsheng.c ... -
关于ViewPager和Fragment
2014-07-07 14:18 1008原文地址:http://www.cnblogs.com/iho ... -
Android移动操作系统的脆弱性分类研究
2014-03-18 14:46 617下载地址:http://www.paper.edu.cn/re ... -
Android实战技巧:深入解析AsyncTask
2014-03-06 11:21 343原文地址:http://blog.csdn ... -
Ubuntu android真机调试
2014-03-06 11:01 445关闭adb服务,切换到root,重启adb服务,离开root ... -
64位Ubuntu配置android环境报错(...adb": error=2, 没有那个文件或目录)
2014-02-07 13:29 580原文地址:http://blog.csdn.net/jayho ... -
【Android 声音处理】MediaPlayer和SoundPool
2014-01-14 17:08 1890原文地址:http://blog.sina ... -
Android自定义组件之一:View详解
2013-07-15 16:08 758原文地址:http://www.eoeandroid.com/ ... -
Android中error inflating class fragment
2013-06-19 17:21 1086原文地址:http://blog.csdn.net/qp120 ... -
拿来主义Android优秀开源项目
2013-06-05 11:57 891http://dengzhangtao.iteye.com/b ... -
android sqlite db-journal文件产生原因及说明
2013-06-05 11:37 3556原文地址:http://blog.csdn.net/chthq ... -
Android系统自带Camera方向判别
2013-05-22 16:40 663使用了OrientationEventListener, 也就 ... -
android onTouchEvent和setOnTouchListener中onTouch的区别
2013-03-27 10:35 728原文地址:http://blog.csdn ... -
Android源码编译整理总结
2013-01-08 11:37 678原文地址:http://www.cnblogs.com/hoj ... -
安卓图表引擎AChartEngine(一) - 简介
2012-12-20 17:47 967原文地址:http://blog.csdn.net/lk_bl ... -
微技巧:Android手机隐藏指令大全
2012-12-07 11:36 763原文地址:http://news.xinhuanet.com/ ... -
自定义控件(attrs定义属性的使用)
2012-12-04 11:38 1146这里为了演示使用自定义变量,字体大小改用自定义的属性。 首先 ... -
二进制在数学中的妙用
2012-11-14 15:50 801原文地址:http://blog.csdn.net/hackb ... -
国外程序员推荐:每个程序员都应读的书
2012-11-06 10:58 797原文地址:http://blog.jobbole.com/58 ...
相关推荐
在本篇文章中,我们将深入探讨`OnItemClickListener`的`position`和`id`参数,以及它们在实际应用中的差异。 首先,`OnItemClickListener`是`AdapterView`接口的一个实现,适用于包括ListView在内的多种列表视图。...
在Android开发中,ListView是一个非常重要的组件,它用于展示大量数据列表,用户可以通过滚动来查看更多的条目。本文将从初级到高级详细讲解ListView的使用,包括基础设置、复杂列表的构建、自定义适配器以及如何...
在Android中,我们通常通过Adapter来连接ListView和数据源,Adapter负责将数据转化为可显示的视图。 1. 创建Adapter:自定义一个继承自BaseAdapter的类,实现其中的四个关键方法: - getCount():返回数据源的大小...
总结,ListView是Android开发中的核心组件之一,理解并熟练掌握其工作原理和使用技巧对于提升应用的交互体验至关重要。在实际项目中,我们需要根据具体需求灵活运用ListView的各种特性,以实现丰富的功能和优化性能...
1. 创建`ArrayAdapter`对象,并传入`Context`、`Layout`资源ID和音乐列表。 2. 通过`setAdapter`方法将适配器设置给`ListView`。 3. 设置`ListView`的选择模式,例如单选模式`CHOICE_MODE_SINGLE`。 示例代码如下:...
对OnItemClickListener的position和id参数,我相信有些人在这上面走了些弯路。 在使用listview的时候,我们经常会在listview的监听事件中,例如OnItemClickListener(onItemClick)中,或listview的adapter中...
在这个类中,你需要实现`getCount()`(返回列表项的数量)、`getItem(int position)`(获取指定位置的数据)、`getItemId(int position)`(返回数据的ID)以及`getView(int position, View convertView, ViewGroup ...
创建一个继承自BaseAdapter的自定义Adapter,实现其中的`getCount()`(返回数据项数量)、`getItem(int position)`(获取指定位置的数据项)、`getItemId(int position)`(返回数据项ID)和`getView(int position, ...
总之,Android的ListView是处理列表数据的核心组件,理解和熟练掌握其使用技巧对Android开发者至关重要。通过适配器、复用机制、事件监听和优化策略,我们可以构建出高效、用户体验良好的列表界面。
以下是对Android ListView组件的详细解释和示例代码。 首先,我们来看ListView的基本结构。ListView本身只是一个容器,它不包含任何实际的数据或显示内容。要让ListView显示数据,我们需要创建一个适配器,适配器的...
本篇文章将深入探讨如何在Android中结合ListView和Adapter,以及通过一个简单的实例来说明其工作原理。 1. **ListView的基础理解** - ListView是一个可滚动的视图,用于显示一列可点击的项目。 - 每个列表项通常...
更常用的方式是为ListView设置OnItemClickListener,这样可以监听到每个列表项的点击事件,回调方法`onItemClick(AdapterView<?> parent, View view, int position, long id)`提供了点击的位置和相关数据。...
Android ListView控件添加监听方法的实例详解 Android ListView是一种常用的控件,在Android应用程序中广泛使用。然而,在使用ListView时,经常需要添加监听方法来响应用户的交互操作。今天,我们将详细介绍Android...
### Android ListView 使用详解 #### 一、ListView简介 在Android应用开发中,`ListView`是一种常用的UI组件,用于展示一个可以滚动的项目列表。通过合理的布局设计与数据绑定,开发者可以构建出功能丰富的用户...
在Android开发中,ListView是一种常用的组件,用于展示可滚动的列表数据。在许多情况下,我们需要在ListView中绘制复杂的布局,比如表格。本篇文章将详细解析如何在ListView中实现表格源码,以及涉及到的相关知识点...
这份"安卓Android源码——listView1.rar"压缩包很可能是包含了一个关于ListView使用和自定义的示例项目。在Android开发中,理解ListView的工作原理以及如何有效地优化其性能是非常重要的知识点。 1. **ListView基本...
【ListView控件详解】 在Android开发中,ListView是用于展示大量数据列表的一种核心组件,它在用户界面设计中扮演着重要角色。S1结业考试的上机题目中,ListView显然是一个重点考察的对象,因为它涉及到数据绑定、...