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的时候,一般都会为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方法。
我们可以来看看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); // 响应代码 }