当前位置: 移动技术网 > IT编程>移动开发>Android > Android ListView position详解及实例代码

Android ListView position详解及实例代码

2019年07月24日  | 移动技术网IT编程  | 我要评论

何真宗,三星t220白屏,临汾平阳

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

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网