当给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的代码,终于领会他的意思了。把其中addHeaderView和setAdapter方法贴下来

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(当然也包括getItem, getItemId)等方法的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不正确相关推荐

  1. android 解决listview.notifyDataSetChanged刷新时Imageloader加载图片闪烁问题

    今天,简单讲讲android里再listview调用notifyDataSetChanged刷新界面时,Imageloader加载图片会闪烁的问题. 最近,发现app里的listview图片会出现闪烁 ...

  2. android listview 数据同步,android中ListView数据刷新时的同步方法

    本文实例讲述了android中ListView数据刷新时的同步方法.分享给大家供大家参考.具体实现方法如下: public class Main extends BaseActivity { priv ...

  3. Flutter 28: 图解 ListView/GridView 混用时滑动冲突小尝试

    小菜在学习过程中会在一个 Page 页面同时用到 GridView 和 ListView 或多个 ListView,此时就会遇到常见的滑动冲突问题.小菜尝试了两种解决滑动冲突的方案,仅记录一下基本的使 ...

  4. Android listView 去掉header和footer中的分割线

    Android listView 去掉header和footer中的分割线 方法一: 在listView中加上android:headerDividersEnabled="false&quo ...

  5. android listview headerview 分割线,【我的Android进阶之旅】如何去除ListView中Header View、Footer View中的分割线...

    最近的项目中给ListView 加入了一个Header View之后,发现Header View的下方也有了分割线,很难看,UI要求将Header View的分割器去掉,好吧.现在就来说一说如何如何去 ...

  6. 看代码学知识之(2) ListView无数据时显示其他View

    看代码学知识之(2) ListView无数据时显示其他View 今天看的一块布局是这样的: <!--The frame layout is here since we will be showi ...

  7. 如何关闭iPhone打电话时音频里面的Mac选项

    下面介绍如何关闭打电话时音频里面的Mac选项 以前点一下是直接可以扬声器 现在每次点击都要选择 恶心 关闭方法: 设置-电话-在其他设备上通话,关闭, 然后重启手机 即可 手机挨近笔记本接打电话,真是 ...

  8. 用于解决listview嵌套GridView时显示不全的问题。

    package com.yetu.ofmy; import android.view.MotionEvent; import android.widget.ListView; /** * * @Cla ...

  9. MFC的exe启动时提示应用程序配置不正确,应用程序未能启动错误

    MFC的exe启动时提示应用程序配置不正确,应用程序未能启动错误 老姐笔记本中毒太深于病入膏肓,无奈迫写一程序"曲线救国".刚启动自己写的程序就出现应用程序配置不正确,应用程序未能 ...

最新文章

  1. freeswitch 按键采集_《FreeSWITCH 1.2》:支持页面呼叫控制
  2. LeetCode Minimum Genetic Mutation(dfs,bfs)
  3. 题目1172:哈夫曼树
  4. 【数字信号处理】线性时不变系统 LTI “ 输入 “ 与 “ 输出 “ 之间的关系 ( LTI 系统单位脉冲响应 | 卷积 | 卷积推导过程 )
  5. 【Maven实用技巧】03. Maven 编译打包时如何忽略测试用例
  6. java 1.8.0 安全_RedHat安全更新修复OpenJDK1.8.0版本漏洞
  7. 总是记不住java的IO流用法?用N个问题教你掌握java IO流
  8. php oracle 8.1.7,Oracle 8.1.7在redhat 7.3的安装方法
  9. C++ Maps 映射
  10. PHPMailer如何获取企业微信授权码
  11. 建议Mac M1关闭虚拟内存(交换内存 swap memory)
  12. java 加权平均_SPSS用加权平均值计算百分位数
  13. 2021年安全员-C证(陕西省)考试资料及安全员-C证(陕西省)免费试题
  14. c# sql where in 参数化传值
  15. 为什么要将图片转为base64格式
  16. 大数据架构Spark 进阶
  17. 备份恢复Lesson 07. lmproving Your Backups
  18. 智原领先推出网通ASIC专用28纳米28G可编程SerDes
  19. 萤石把直播嵌在html中,直播组件流程使用说明
  20. 八种常见回归算法解析及代码

热门文章

  1. oracle hibernate 主键,oracle hibernate 主键自增
  2. html按键变色,按键变色.html
  3. 保存到本地_不用任何软件工具找回已保存在本地的网页密码
  4. python plotly spyder显示_Python绘图工具Plotly的简单使用
  5. mysql mha配置idrac远程关机_iDRAC远程管理功能试用_戴尔 PowerEdge R810(Xeon E7520/16GB/3*146GB)_服务器评测与技术-中关村在线...
  6. Notepad++ 配置 Markdown
  7. Python编程基础11:字典
  8. Java讲课笔记28:Path接口和Files工具类
  9. 【HDU5156】Harry and Christmas tree,两种离线的做法
  10. java线程工作内存在栈中吗_JVM常见面试题解析