当ListView有Header时,onItemClick里的position不正确

转载 2015年07月07日 18:31:14

当给ListView加了一个HeaderView后(代码如下),我们发现,onItemClick方法里的position参数的值不是我们所期望的,比如点击ListView的第一行,我们期望的position是0,可是实际上却是1,也就是说,它是从Header而不是从第一行开始计数的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
 
    setContentView(R.layout.home);
 
    mAdapter = new MyAdapter(this);
 
    mListView = (ListView) findViewById(R.id.list);
    mListView.addHeaderView(getLayoutInflater().inflate(R.layout.list_header));
    mListView.setAdapter(mAdapter);
    mListView.setOnClickListener(this);
}
 
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
    doSomething(mAdapter.getItem(position));
}

 Google了下,发现有个老外issue过一个bug,和我遇到的问题一样,不过这个bug被RomainGuy reject掉了,理由是,你用错了,请用getAdapter。这回答的太简洁了,完全没法理解,所以只好又去仔细研究ListView的代码,终于领会他的意思了。把其中addHeaderViewsetAdapter方法贴下来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
 * Add a fixed view to appear at the top of the list. If addHeaderView is
 * called more than once, the views will appear in the order they were
 * added. Views added using this call can take focus if they want.
 * <p>
 * NOTE: Call this before calling setAdapter. This is so ListView can wrap
 * the supplied cursor with one that that will also account for header
 * views.
 *
 * @param v The view to add.
 * @param data Data to associate with this view
 * @param isSelectable whether the item is selectable
 */
public void addHeaderView(View v, Object data, boolean isSelectable) {
    if (mAdapter != null) {
        throw new IllegalStateException(
                "Cannot add header view to list -- setAdapter has already been called.");
    }
 
    FixedViewInfo info = new FixedViewInfo();
    info.view = v;
    info.data = data;
    info.isSelectable = isSelectable;
    mHeaderViewInfos.add(info);
}
 
/**
 * Sets the data behind this ListView.
 *
 * The adapter passed to this method may be wrapped by a {@link WrapperListAdapter},
 * depending on the ListView features currently in use. For instance, adding
 * headers and/or footers will cause the adapter to be wrapped.
 *
 * @param adapter The ListAdapter which is responsible for maintaining the
 *        data backing this list and for producing a view to represent an
 *        item in that data set.
 *
 * @see #getAdapter()
 */
@Override
public void setAdapter(ListAdapter adapter) {
    if (null != mAdapter) {
        mAdapter.unregisterDataSetObserver(mDataSetObserver);
    }
 
    resetList();
    mRecycler.clear();
 
    if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
        mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
    else {
        mAdapter = adapter;
    }
 
    //其它的一些代码这里省略之...
}

 

 

从代码和注释里都可以很清楚的得知,addHeaderView一定要在setAdapter之前调用,如果不这样做,addHeaderView会抛出一个异常。Android为什么要这样?这是因为,在setAdapter的时候,会针对我遇到的这种情况(也就是添加Header后position不正确的这种情况)做些特殊的处理。setAdapter在内部判断了当前ListView是否有Header或者Footer,如果没有,就直接使用参数传进来的adapter;如果有,则用一个decorated的HeaderViewListAdapter来替换参数。这个HeaderViewListAdapter的使命,就是排除Header和Footer,让position(当然也包括getItemgetItemId)等方法的position参数)正确返回。

分析到这里,解决方案就出来了:在onItemClick不要直接使用我们声明的adapter,而是用ListView里的那个decorated adapter。获取它的方法就是调用parent.getAdapter()。当然,如果ListView没有Header和Footer,直接使用声明的adapter也没有问题,不过为了避免出错,还是统一使用decorated adapter比较好。

把onItemClick改成下面这样,就可以了

1
2
3
4
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
    doSomething(parent.getAdapter().getItem(position));
}

 本文由Roy最初发表于:http://blog.chengbo.net/2012/03/09/onitemclick-return-wrong-position-when-listview-has-headerview.html,你可以在保持文章完整和保留本声明的情况下转帖、分发和印刷等。

当为ListView添加Header以后,在onitemClick里面position位置不正确处理策略

最近在项目里面有为listView添加头信息的需求,但是添加之后发现了一个有趣的问题,就是添加之后,在onitemCLick里面的position发生错乱了,首先想到的是直接手动+1,但是这种处理方法...
  • lvshuchangyin
  • lvshuchangyin
  • 2016年09月27日 10:09
  • 731

当ListView有Header时,onItemClick里的position不正确的解决方案

Fri, Mar 9, 2012 今天在做项目的时候,遇到一个问题,记录下来。 当给ListView加了一个HeaderView后(代码如下),我们发现,onItemClick方法里的positi...
  • cs15229216584
  • cs15229216584
  • 2016年11月22日 08:46
  • 150

ListView 的position不正确的时如何处理

当给ListView加了一个HeaderView后(代码如下),我们发现,onItemClick方法里的position参数的值不是我们所期望的,比如点击ListView的第一行,我们期望的posit...
  • a417348199
  • a417348199
  • 2014年08月11日 18:30
  • 476

解决ListView当中还有ListView onItemClick点击事件问题

很久没有写帖子了 一直挺忙 但是这个帖子 惦记好久了  应该记录一下  一张图描述 使用场景 如图所示 我外层是一个 可上拉刷新 下拉加载更多的的控件ListView 里面是一个 可动态...
  • wujian543
  • wujian543
  • 2016年08月31日 18:03
  • 618

解决ListView的getView()方法中View设置监听position错乱的问题

最近在项目中遇到了类似微信朋友圈的功能,可以点赞,评论和分享。类似这样的 这是ListView的一个item,点击右下角的view弹出一个popupWindow,然后popupWindow上面还有三...
  • suncold123
  • suncold123
  • 2017年04月07日 22:49
  • 631

Android依赖注入类库 Butter Knife的使用

我们做移动端开发,每天写代码时几乎都会跟各种View打交道,大量的声明和findViewById()让人感到厌烦,但是又不得不写,今天给大家推荐一个第三方开源注解工具,ButterKnife,大家可自...
  • zhangxmu
  • zhangxmu
  • 2015年11月02日 19:42
  • 2574

ListView添加头部之后出现位置获取错乱的问题解决方案

/**  * Add a fixed view to appear at the top of the list. If addHeaderView is  * called more than ...
  • blueZhangFun
  • blueZhangFun
  • 2015年11月13日 10:13
  • 2159

ListView的Intent跳转详情页, 滑动与点击Position错乱导致数据混乱问题解决

问题描述具体问题是这样:今天在项目中遇到了从一个ListView界面,通过点击Item中的控件(我这里做的是图片,后改为布局)跳转到详情页面,并且将部分数据传入到下一个Activity。来个图 问题...
  • tsaopin
  • tsaopin
  • 2015年08月20日 19:33
  • 2014

ListView的onItemClickListener不起作用解决办法

这次做课程设计,虽然做的很粗糙,但是在做的过程还是积累了一些东西,有动手就会有收获,这里记录一些吧。 listview在android开发中很地方都用到了,通常我们需要定制item里面的视图,就要重写...
  • u012554102
  • u012554102
  • 2015年07月11日 22:58
  • 841

ListView添加动态悬浮header的另类方式

今天看了一篇文章是搞ListView动态悬浮header的, 我又结合了WheelView的item的绘制方式,最终终于有了这篇博客,在讲解实现方式之前,我们先来看看要实现的效果。要实现这种效果有很多...
  • qibin0506
  • qibin0506
  • 2015年11月19日 12:53
  • 7275
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:当ListView有Header时,onItemClick里的position不正确
举报原因:
原因补充:

(最多只允许输入30个字)