Android ListView position详解及实例代码_Android

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

    在使用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中,理应是数据源的索引位置。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
, listview
, position
, position详解
position详细介绍
android listview详解、android listview实例、android创意实例详解、listview position、listview获取position,以便于您获取更多的相关知识。

时间: 2024-09-15 05:43:44

Android ListView position详解及实例代码_Android的相关文章

Android ListView position详解及实例代码

我们在使用ListView的时候,一般都会为ListView添加一个响应事件android.widget.AdapterView.OnItemClickListener.对OnItemClickListener的position和id参数,我相信有些人在这上面走了些弯路. 在使用listview的时候,我们经常会在listview的监听事件中,例如OnItemClickListener(onItemClick)中,或listview的adapter中(getView.getItem.getIte

Android ListView组件详解及示例代码_Android

Android 列表组件 ListView 列表组件是开发中经常用到组件,使用该组件在使用时需要为它提供适配器,由适配器提供来确定显示样式和显示数据. 下面看一个例子: 新建一个项目Lesson8_ListViewTest,Activity name是MainListViewTest . MainListViewTest.java的代码是: package android.basic.lesson8; import android.app.Activity; import android.os.

Android 文件选择器详解及实例代码_Android

     本文给大家讲解下Android文件选择器的使用.实际上就是获取用户在SD卡中选择的文件或文件夹的路径,这很像C#中的OpenFileDialog控件.        此实例的实现过程很简单,这样可以让大家快速的熟悉Android文件选择器,提高开发效率.        网上曾经见到过一个关于文件选择器的实例,很多人都看过,本实例是根据它修改而成的,但更容易理解,效率也更高,另外,本实例有自己的特点:        1.监听了用户按下Back键的事件,使其返回上一层目录.       

Android GPS定位详解及实例代码_Android

      GPS定位是智能手机上一个比较有意思的功能,LBS等服务都有效的利用了GPS定位功能.本文就跟大家分享下Android开发中的GPS定位知识.        一.Android基础知识准备        1.Activity类        每一种移动开发环境都有自己的基类.如J2ME应用程序的基类是midlets,BREW的基类是applets,而Android程序的基类是Activity.这个activity为我们提供了对移动操作系统的基本功能和事件的访问.这个类包含了基本的构造

Android语音识别技术详解及实例代码_Android

   今天从网上找了个例子实现了语音识别,个人感觉挺好玩的,就把代码贴出来与大家分享下:          Android中主要通过RecognizerIntent来实现语音识别,其实代码比较简单,但是如果找不到设置,就会抛出异常ActivityNotFoundException,所以我们需要捕捉这个异常.而且语音识别在模拟器上是无法测试的,因为语音识别是访问google云端数据,所以如果手机的网络没有开启,就无法实现识别声音的!一定要开启手机的网络,如果手机不存在语音识别功能的话,也是无法启用

ReactNative Alert详解及实例代码_Android

Alert顾名思义一就是一个警告框,一般使用情况比如:退出登录,清楚缓存,提示修改密码等等...ReactNative中的Alert只有一个静态方法alert()其中有四个参数:标题,信息,按钮和按钮类型 在Android按钮至多有三个 下面是使用情况: 实例代码: /** * Created by Administrator on 2016/9/12. */ import React, {Component} from 'react'; import { StyleSheet, View, T

Android 混合动画详解及实现代码_Android

Android 混合动画 在Android开发,我们会经常使用到动画,但是简单的一种动画(如旋转.缩放.渐变.位移等)有时候并不能满足我们项目的要求,这时候就需要运用到混合动画,那么在安卓中是如何实现一个炫酷的混合动画,下面是一个混合动画实现的其中一个实现方式: 1.首先要在res目录下建立一个anim文件,在anim建立一个hybrid.xml文件如下: <?xml version="1.0" encoding="utf-8"?> <set xm

Android listview与adapter详解及实例代码_Android

一个ListView通常有两个职责. (1)将数据填充到布局. (2)处理用户的选择点击等操作. 第一点很好理解,ListView就是实现这个功能的.第二点也不难做到,在后面的学习中读者会发现,这非常简单. 一个ListView的创建需要3个元素. (1)ListView中的每一列的View. (2)填入View的数据或者图片等. (3)连接数据与ListView的适配器. 也就是说,要使用ListView,首先要了解什么是适配器.适配器是一个连接数据和AdapterView(ListView就

Android App增量更新详解及实例代码_Android

Android App增量更新实例--Smart App Updates        介绍 你所看到的,是一个用于Android应用程序增量更新的开源库. 包括客户端.服务端两部分代码. 原理 自从 Android 4.1 开始,Google引入了应用程序的增量更新. Link: http://developer.android.com/about/versions/jelly-bean.html Smart app updates is a new feature of Google Pla