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

2023-11-16

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

@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方法贴下来

/**
 * 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改成下面这样,就可以了

@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,你可以在保持文章完整和保留本声明的情况下转帖、分发和印刷等。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ListView 的position不正确的时如何处理 的相关文章

随机推荐

  • PostCSS的配置文件

    Vue中使用Vant组件库时 需要使用rem单位 使用了以下两个工具 postcss pxtorem 是一款 postcss 插件 用于将单位转化为 rem lib flexible 用于设置 rem 基准值 在使用PostCSS 时 提供
  • 区块链在供应链领域的应用案例

    案例一 布比物链构建基于区块链的有品质保证且诚信公证的供应链系统 面对众多供应链领域存在的问题 布比基于区块链技术构建了物链 物链充分利用区块链高可信共识 低成本安全 分布式账本和高效链接多中心的特点 整合先进的物联网技术 推出了 品质驱动
  • 环境—虚拟机Ubuntu18的VScode出现XHR:timeout

    解决 Error while fetching extensions XHR timeout VScode改代理 本台虚拟机 测试无效 windows下改host 本台虚拟机 测试无效 windows下改时区服务器 本台虚拟机 测试有效 D
  • 弱口令漏洞与验证码绕过——渗透day04

    目录 一 基于远程服务的弱口令攻击 一 服务暴力破解软件 二 实验 二 基于web的弱口令测试 一 基于表单的暴力破解 二 验证码绕过 on client 1 通过Script Blocker Ultimate插件绕过验证码 2 通过bur
  • Qt封装一个类管理moveToThread( )正确的开启多线程、安全的退出线程的实例

    看本篇的文章基础在于你已经懂得了简单的利用moveToThread的方法创建出一个线程 不会的话可以查看本篇博客 总结 QT 多线程 处理密集时的界面响应保持 运用 MultMoveToThread testObject new MultM
  • 记一次mysql进程无法启动的解决方案

    莫名其妙数据库崩了 试了很多方案启动不了 然后不经意看到 usr local mysql data目录下几个日志文件特别大 删除之后就能重启了 rw rw 1 mysql mysql 4497955 Mar 3 18 29 xxxx php
  • 【Unity Optimize】使用图集(Sprite Atlas)优化项目

    目录 1 图集 Sprite Atlas 介绍 2 创建与配置Sprite Atlas 2 1 创建Sprite Atlas 2 1 1 Unity2D项目 2 1 2 Unity3D项目 2 2 配置Sprite Atlas 2 3 注意
  • PLC接线详解

    PLC常见的输入设备有按钮 行程开关 接近开关 转换开关 拨码器 各种传感器等 输出设备有继电器 接触器 电磁阀等 想学好电气 必须先学会接线 如果线都接不好的话 设备出现问题时 依然是无从下手 正确地连接输入和输出线路 是保证PLC可靠工
  • 射频电路学习之LC振荡电路

    文章目录 前言 一 串联谐振电路 二 并联谐振电路 三 谐振电路的本质 总结 前言 谐振是指 当外力作用的频率与系统固有的振荡频率相同或非常接近时 振幅急剧增大的现象 其中产生谐振时的频率成为谐振频率 谐振是正弦电路中的一种特殊现象 回路也
  • IBM DISK queue_depth参数调整

    queue depth参数会影响disk i o性能 特别是在数据库等i o密集性应用中 适当调整设置此参数 会提高整体应用的性能 下面是在AIX 5 3 IBM ds4300上调整此参数的 步骤及注意事项 记录一下 下面物理磁盘hdisk
  • Windows 11 提升软件打开速度

    设置 gt 辅助功能 gt 视觉效果 gt 动画效果 关闭 设置 gt 辅助功能 gt 视觉效果 gt 透明效果 关闭 设置 gt 应用 gt 启动 都关闭
  • 08-wait 和 sleep 的区别

    1 源码 sleep public class Thread implements Runnable public static native void sleep long var0 throws InterruptedException
  • Qt实现图像自适应窗口大小之scaled()函数使用

    很多应用都需要显示图片 比如视频类应用 拍照类应用 但是在大数情况下用户都会改变窗口大小 以获得最佳效果 在Qt中如果只设置了显示图片而没有对自适应窗口做出设置 用户拖拽边框的时候 整个控件上就会出现大片空白部分 怎么解决这个问题呢 QIm
  • Python基础(四):Python函数和模块的讲解和应用

    一 前言 山东省小学已将Python内容纳入教材 江省已将信息技术教材VB编程语言替换为Python 计算机二级考试加入 Python语言程序设计 科目 越来越多的岗位也需要Python技能 Python连续4年成功登顶最流行的编程语言榜单
  • Git安装以及基本配置

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 提示 以下是本篇文章正文内容 下面案例可供参考 一 Git安装以及配置 git官网 https git scm com downloads 选择适合的版本进入下载 然后傻瓜式
  • 两个数组去重!

    var a1 1 2 3 4 5 var b1 1 2 var c1 a1 filter a gt return b1 some c gt c a 两个数组可快速对比去重
  • crontab日志包命令找不到和乱码问题

    crontab设置的定时任务 执行脚本报错命令找不到和乱码 使用crontab时的运行环境已经不是用户环境了 因此原本用户下的一些环境变量的设 置就失效了 因为我的命令path设置到了 etc profile里了 所以在crontab运行不
  • 【Flutter 1-8】Flutter教程Dart语言——控制语句

    控制语句 Dart语言的控制语句跟其他常见语言的控制语句是一样的 基本如下 if 和 else for 循环 while 和 do while 循环 break 和 continue switch 和 case assert If 和 El
  • centos 6.6 编译安装PHP7.0.5

    PHP7 0正式版也出来了 今天编译安装了一下 写下安装步骤 我是在centos6 6 环境中编译的 如下 下载地址http cn2 php net distributions php 7 0 5 tar gz 安装编译所需的包 如遇见部分
  • ListView 的position不正确的时如何处理

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