ListView 的position和id的区别

    xiaoxiao2022-06-29  45

    1 . listview adapter 的getView方法中的position 代表传入adapter的数组数据,从0开始

    2.. listview onItemClick 方法中的position 代表 当前点中的view的位置,这个view包括headview 和 footview,所以,所以,如果有headview的话,position用户点击的adapter位置从1开始

    具体讲解:

    引用自: http://www.cnblogs.com/xiaorenwu702/p/5672315.html

    具体内容:

    ListView 的position和id的区别

    我们在使用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的实现

     

    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; } 可以看出,如果这个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() 中被调用 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_<span style="margin: 0px; padding: 0px;">POSITION</span> && 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事实上就是ListView中被点击的view的位置。注意,在ListView中是不负责处理headerView和footViewer的,所以,这个位置应该是这个被点击的view在数组[所有的headerView,用户添加的view,所有的 footerView]中的位置(请自行参考HeaderViewListAdapter的getView实现)。而id是来自于adapter.getItemId( position)。   对于ArrayAdapter的getItemId函数,实现就是return  position。id和 position是一致的。 然而,对于HeaderViewListAdapter

     

    public long getItemId(int <span style="margin: 0px; padding: 0px;">position</span>) { int numHeaders = getHeadersCount(); if (mAdapter != null && <span style="margin: 0px; padding: 0px;">position</span> >= numHeaders) { int adjPosition = <span style="margin: 0px; padding: 0px;">position</span> - numHeaders; int adapterCount = mAdapter.getCount(); if (adjPosition < adapterCount) { return mAdapter.getItemId(adjPosition); } } return -1; } 实现逻辑是,如果 position指向了headerView或 footerView,那么返回-1,否则,将返回在用户view数组的位置。 也就是说 id= position-headerView的个数(id < headerviewer的个数+用户view的个数),否则=-1 因此,OnItemClickListener的正确实现如下:

     

    void onItemClick(AdapterViewparent, View view, int <span style="margin: 0px; padding: 0px;">position</span>, long id){ if(id == -1) { // 点击的是headerView或者<span style="margin: 0px; padding: 0px;">footerView</span> return; } int realPosition=(int)id; T item=getItem(realPosition); // 响应代码 }

    转载请注明原文地址: https://ju.6miu.com/read-1125310.html

    最新回复(0)