Android ListView position详解及实例代码

 更新时间:2016年10月14日 15:52:27   投稿:lqh  
这篇文章主要介绍了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 EditText实现输入金额类型详解

    Android EditText实现输入金额类型详解

    EditText是Android中一个非常实用的控件,有很多InputType,可以来达到不同的输入效果,下面这篇文章主要给大家介绍了关于Android EditText实现输入金额类型的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-09-09
  • Flutter实现App功能引导页

    Flutter实现App功能引导页

    这篇文章主要为大家详细介绍了Flutter实现App功能引导页,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • Android开发之线程通信详解

    Android开发之线程通信详解

    这篇文章主要为大家详细介绍了Android开发中线程间通信的相关资料,文中的示例代码讲解详细,对我们学习Android有一定的帮助, 需要的可以了解一下
    2022-11-11
  • 解析Android横竖屏切换的问题

    解析Android横竖屏切换的问题

    本篇文章是对Android中横竖屏切换的问题进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • Android应用中仿今日头条App制作ViewPager指示器

    Android应用中仿今日头条App制作ViewPager指示器

    这篇文章主要介绍了Android应用中仿今日头条App制作ViewPager指示器的例子,一般就是导航条在翻页时的动态字体变色效果,需要的朋友可以参考下
    2016-04-04
  • android监听View加载完成的示例讲解

    android监听View加载完成的示例讲解

    今天小编就为大家分享一篇android监听View加载完成的示例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • Android Studio 运行按钮灰色的完美解决方法

    Android Studio 运行按钮灰色的完美解决方法

    今天新建项目的时候突然发现编译后运行按钮为灰色,今天小编给大家带来了Android Studio 运行按钮灰色的完美解决方法,非常不错,对大家的需要或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-10-10
  • Android 开机广播的使用及配置

    Android 开机广播的使用及配置

    在配置文件AndroidManifest.xml中向系统注册receiver,子节点 intent-filter表示接收
    2013-02-02
  • Android带进度的圆形进度条

    Android带进度的圆形进度条

    这篇文章主要为大家详细介绍了Android带进度的圆形进度条,实现自定义View,自定义属性,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • Android中ExpandableListView的用法实例

    Android中ExpandableListView的用法实例

    这篇文章主要介绍了Android中ExpandableListView的用法,以实例形式展示了Android中的下拉list控件的用法,需要的朋友可以参考下
    2014-10-10

最新评论