ListView position
在使用listview的时候,我们经常会在listview的监听事件中,例如OnItemClickListener(onItemClick)中,或listview的adapter中(getView、getItem、getItemId等)看到position这个变量。在我们没有为listview添加headerView时,position和数据源集合的索引是一致的,当添加了headerView之后,某些地方的position值就会发生变化,如果不理解清楚,经常会犯一些糊涂。
在listview添加了headerView后, 会将所有view交给HeaderViewListAdapter来处理,所以我们要在setAdapter之前添加headerView或footerView,否则将显示不出来。
@Override
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;
}
先看看HeaderListAdapter中几个带position参数的方法实现,我们可以看到在传出的position为adjPosition,而adjPosition均为我们自动去掉了headerView的数量,所以adapter中几个带position变量的方法,得到的position值均和数据源集合索引一致,仔细翻看HeaderListAdapter中所有需要传出position的方法,position的值都是自动减去了headerView数量。
public View getView(int position, View convertView, ViewGroup parent) {
// Header (negative positions will throw an ArrayIndexOutOfBoundsException)
int numHeaders = getHeadersCount();
if (position < numHeaders) {
return mHeaderViewInfos.get(position).view;
}
// Adapter
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getView(adjPosition, convertView, parent);
}
}
// Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)
return mFooterViewInfos.get(adjPosition - adapterCount).view;
}
public Object getItem(int position) {
// Header (negative positions will throw an ArrayIndexOutOfBoundsException)
int numHeaders = getHeadersCount();
if (position < numHeaders) {
return mHeaderViewInfos.get(position).data;
}
// Adapter
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getItem(adjPosition);
}
}
// Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)
return mFooterViewInfos.get(adjPosition - adapterCount).data;
}
public long getItemId(int position) {
int numHeaders = getHeadersCount();
if (mAdapter != null && position >= numHeaders) {
int adjPosition = position - numHeaders;
int adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getItemId(adjPosition);
}
}
return -1;
}
我们再来分析分析OnItemClickListener的相关源码,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_POSITION &&
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对应motionPosition,而motionPosition通过调试,我们发现就是listview中被点击的位置,所以我们经常在onItemClick中需要获取数据源集合中某个item时,会习惯性写这样代码:sourceList.get(position-listView.getHeaderViewsCount())。
我们发现onItemClick还有一个参数,其实就是上面源码中传递给performItemClick的第三个参数,而第三个参数是通过调用adapter的getItemId将motionPosition减去了headerView的数量,所以这个参数的结果是与数据源集合的索引一致的。也就是说,我们完全可以使用onItemClick的id这个参数,这个参数是和数据源集合的索引一致的。
另外我们需要注意,如果数据源没有内容,则id的值会为-1,所以我们在使用id时,需要对id做适当判断。
总结:在OnItemClickListener的onItemClick方法中,当我们需要获取点击listview对应的数据源索引时,使用id参数即可。另外除了onItemClick的position参数是点击listview对应view的位置外,adapter中所有position均为数据源索引位置。其实换个角度更容易记,在listview中,position理应是listview中view对应的位置,而在adapter中,理应是数据源的索引位置。
ListView position的更多相关文章
- android菜鸟学习笔记14----Android控件(三) ListView的简单使用
MVC模式: MVC的基本原理就是通过Controller连接View和Model.当View中所显示的数据发生变化时,会通知Controller,然后由Controller调用Model中的相关方法 ...
- UWP 拉勾客户端
前些天, 用 Xamarin.Forms (XF) 将就着写了个拉勾的 UWP 和 Android 的客户端. XF 对 Android 和 IOS 的支持做的很到位, 但是对 UWP 的支持目前仅 ...
- Android再学习-便签开发小结-20141119
这几天的便签开发,首先遇到的问题就是数据库操作问题.现在已经可以读写数据库了,并能将数据放在正确的位置显示. 专门建立了一个数据库操作的包,命名为"...database".新建一 ...
- 第六章:Reminders实验:第二部分[Learn Android Studio 汉化教程]
Learn Android Studio 汉化教程 Reminders Lab: Part 2 This chapter covers capturing user input through the ...
- 用Vue来实现音乐播放器(十六):滚动列表的实现
滚动列表是一个基础组件 他是基于scroll组件实现的 在base文件夹下面创建一个list-view文件夹 里面有list-view.vue组件 <template> < ...
- 【转】android中ListView的定位:使用setSelectionFromTop实现ListView的position的保持
如果一个ListView太长,有时我们希望ListView在从其他界面返回的时候能够恢复上次查看的位置,这就涉及到ListView的定位问题: 解决的办法如下: 1 2 3 4 5 6 7 // 保存 ...
- ListView addHeaderView 对 position 的影响
1. 在 public View getView(int position, View convertView, ViewGroup parent) 中position 和 是否有headerView ...
- ListView配合CheckBox出现position位置错误的解决
最近做checkBox和ListView配合使用,想把position的位置传入到 checkBox的onCheckedChanged,于是我就在getView的时候, 把position通过chec ...
- ListView的position的保持
需求场景: 一个ListView页面,滑动阅读到某一位置,然后退出页面,下次再进入页面的时候,想要直接滑动到上次阅读的位置. 方案1: 页面退出的时候,ListView.getFirstVisible ...
随机推荐
- 《Linux内核--分析Linux内核创建一个新进程的过程 》 20135311傅冬菁
20135311傅冬菁 分析Linux内核创建一个新进程的过程 一.学习内容 进程控制块——PCB task_struct数据结构 PCB task_struct中包含: 进程状态.进程打开的文件. ...
- 《Linux内核分析与设计》读书笔记二
第五章 5.1 与内核通信57 系统调用在用户空间进程和硬件设备之间添加了一个中间层,该层主要作用有三个: 首先它为用户空间提供了一种硬件的抽象接口,举例来说当需要读写文件的时候,应用程序就可以不去管 ...
- 团队作业(五)——旅游行业的手机App
首先是作业要求: 在PM 带领下, 每个团队深入分析下面行业的App, 找到行业的Top 5 (从下面的三个备选中,任选一个行业即可) 英语学习/词典App 笔记App 旅游行业的手机App 我们选择 ...
- 四则运算生成程序——GUI支持和部分功能改进
项目成员:张金生 张政 工程地址: https://coding.net/u/jx8zjs/p/paperOne/git ssh://git@git.coding.net:jx8zjs/pap ...
- Git从零开始(一)
一.首先windows安装git客户端 官网下载地址:https://git-for-windows.github.io/,这里下载会很慢,我试了好几次都失败了. 百度网盘资源: https://pa ...
- powershell远程管理服务器磁盘空间的实现代码
一.启用远程管理 1.将管理服务器的trusthost列表改为* 运行Set-item wsman:localhostclienttrustedhosts ?value * 2.在远程服务器上运行En ...
- 【Java并发编程】之十四:图文讲述同步的另一个重要功能:内存可见性
加锁(synchronized同步)的功能不仅仅局限于互斥行为,同时还存在另外一个重要的方面:内存可见性.我们不仅希望防止某个线程正在使用对象状态而另一个线程在同时修改该状态,而且还希望确保当一个线程 ...
- 我为什么放弃MySQL?选择了MongoDB
最近有个项目的功能模块,为了处理方便,需要操作集合类型的数据以及其他原因.考虑再三最终决定放弃使用MySQL,而选择MongoDB. 两个数据库,大家应该都不陌生.他们最大的区别就是MySQL为关系型 ...
- MT【195】三次函数
(2016年清华大学自主招生暨领军计划试题) 已知$x,y,z\in \mathbf{R}$,满足$x+y+z=1,x^2+y^2+z^2=1$,则下列结论正确的有( ) A.$xyz$的最大值为$0 ...
- bzoj1038
这是一道非常有意思的题目 Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 我们可以用一 ...