android listview footview 点击,ListView中headView和footView  --->转载

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

abstractgetView (int

position, View convertView,

这里也有一个position。

初步接触ListView的同学,一般会直接继承ArrayAdapter,然后(比如我),就想当然的认为OnItemClick的position和getView的position是一样的啊。于是我们就getItem(position)来获取相应的数据。

那么这段代码有没有错呢?如果有错的话,在什么情况会出错呢?

第一个问题的答案是,当我们为ListView添加headerView或者footerView之后,这段代码就不一定是我们想要的了。

出现问题的原因在于,当我们为ListView添加headerView或者footerView之后,ListView在setAdapter时,做了一些事情,这导致,Adapter和OnItemClickListener中的position含义发生了变化。

我们可以来看看ListView中setAdapter的实现

可以看出,如果这个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是怎么传进来的。

2497 private class PerformClick extends WindowRunnnable implements Runnable {

2498 int mClickMotionPosition;

2500 public void run() {

2501 // The data has changed since we posted this action in the event queue,

2502 // bail out before bad things happen

2503 if (mDataChanged) return;

2505 final ListAdapter adapter = mAdapter;

2506 final int motionPosition = mClickMotionPosition;

2507 if (adapter != null && mItemCount > 0 &&

2508 motionPosition != INVALID_POSITION &&

2509 motionPosition < adapter.getCount() && sameWindow()) {

2510 final View view = getChildAt(motionPosition - mFirstPosition);

2511 // If there is no view, something bad happened (the view scrolled off the

2512 // screen, etc.) and we should cancel the click

2513 if (view != null) {

2514 performItemClick(view, motionPosition, adapter.getItemId(motionPosition));

2515 }

2516 }

2517 }

2518 }

可以看到,position事实上就是ListView中被点击的view的位置。注意,在ListView中是不负责处理headerView和footViewer的,所以,这个位置应该是这个被点击的view在数组[所有的headerView,用户添加的view,所有的footerView]中的位置(请自行参考HeaderViewListAdapter的getView实现)。而id是来自于adapter.getItemId(position)。

对于ArrayAdapter的getItemId函数,实现就是return

position。id和position是一致的。

然而,对于HeaderViewListAdapter

188 public long getItemId(int position) {

189 int numHeaders = getHeadersCount();

190 if (mAdapter != null && position >= numHeaders) {

191 int adjPosition = position - numHeaders;

192 int adapterCount = mAdapter.getCount();

193 if (adjPosition < adapterCount) {

194 return mAdapter.getItemId(adjPosition);

195 }

196 }

197 return -1;

198 }

实现逻辑是,如果position指向了headerView或footerView,那么返回-1,否则,将返回在用户view数组的位置。

也就是说

id=position-headerView的个数(id <

headerviewer的个数+用户view的个数),否则=-1

因此,OnItemClickListener的正确实现如下:

1

void onItemClick(AdapterViewparent,

View view,int position,long id){

2

if(id

{

3

//

点击的是headerView或者footerView

4

return;

5

}

6

int realPosition=(int)id;

7

T

item=getItem(realPosition);

8

//

响应代码

9

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值