Android Listview:更新不可见的视图或禁用回收

时间:2015-11-10 14:56:17

标签: android listview android-listview android-scrollview

我正在设计一款Android游戏,我试图使用ListView。该列表使用BaseAdapter,并填充ArrayList。当用户按下确定按钮时,我滚动到列表顶部,然后遍历列表中的每个士兵。我设置了士兵的一个子视图的背景drawable,这样它就是一个显示" hit"或"想念"。我使用了一个Handler.postDelayed(),以便每个动画都可以在它之前完成。

问题是我无法修改不可见的视图。我的列表中一次最多可包含13名士兵,但最多只能显示5名士兵。所以一旦我击中了第六名士兵,我就会因使用ListView.getChildAt(soldierArrayIndex)而得到一个空指针异常。我的解决方案是在getChildAt()调用之前添加smoothScrollTo(soldierArrayIndex)以使其可见,但问题仍然存在。

所以我的问题并非如此"如何修复我的代码?"。我更想知道是否有办法禁用ListView的回收。我使用getChildAt()的原因是因为我需要在它返回的视图上使用findViewById(),然后修改ID找到的视图。但是,如果视图从未被回收,则getChildAt()将不会返回null。

我的另一个想法是只使用滚动视图,输入我创建的13个士兵视图实例,然后设置我目前没有使用的那些"去掉#34;。我唯一的问题是我不知道如何迭代这些观点。

TL; DR:如何更新列表视图中当前不可见的视图(它们目前是"已回收")?

1 个答案:

答案 0 :(得分:1)

我认为你在这里混淆了模特和视图。

适配器视图采用通常可以访问整个数据集的适配器。因此,即使您的ListView只渲染屏幕上可见的项目,您仍然可以通过调用适配器上的getItem(位置)来访问屏幕外项目。

您似乎直接在适配器上调用getView。

我建议您不要这样做,因为这不是AdapterViews和Adapters的设计方式。相反,当模型中的某些内容发生更改时(通过notifyDataSetChanged),您需要向ListView指示并将其留给ListView以代表您调用适配器的getView方法。

我想事件的顺序是这样的:

  1. 更新士兵对象
  2. 在你的适配器上调用notifyDataSetChanged,告诉你的ListView需要重绘东西
  3. ListView遍历每个调用getView(int position,View convertView,ViewGroup parent)的可见Soldier项目。
  4. 适配器中的getView实现将Soldier置于指定位置,并确定View在该时间点的外观。
  5. 对于“offscreen”士兵(在ListView的滚动区域中看不到的士兵),ListView不需要渲染它们,因此它不会在这些位置上调用getView。

    但是,如果屏幕外的士兵现在滚动到视图中,ListView将使用该阵列中士兵的位置调用适配器的getView方法。

    最后,如果您希望更精细地控制AdapterView如何更新自身,您可以考虑使用RecyclerView,因为它允许您逐项通知更改。