【问题标题】:ListView and variable height items causes scroll problemsListView 和可变高度项导致滚动问题
【发布时间】:2014-01-03 08:59:25
【问题描述】:

我有一个ListView,用于滚动字段列表、文本和照片。 两个高度都是动态的:textview可以包含一个很长的段落或一个句子,并且图像被缩放以适应宽度,因此高度是可变的(你可以看到照片)。有些项目甚至没有图像。 这使得物品的高度非常不均匀。有一个项目可以有 2 个屏幕长,而另一个只有一行文本。

我让它工作等等。但是当我向上滚动时,当循环视图插入到顶部时,滚动位置会跳跃大约与新孩子的大小。向下滚动完美...

我或多或少地理解为什么,显然回收的视图在大小上完全不同,这使得一些滚动算法失败,无论它在哪里。

我已经阅读了关于覆盖 itemType()itemTypeCount 的信息,但我不知道这是否与我的问题有关。在我做的测试中,它没有(神奇地)起作用。

这可以很容易地解决吗,这里和那里有什么技巧或魔术 requestLayout 吗?

有人建议写一个视图回收器来解决这个问题:问题listview scrolls quite junky when therre are different row heights

View recycler 会像听起来那么复杂吗?

抱歉这个抽象问题..

【问题讨论】:

  • 请发布您的适配器布局和适配器 getView 代码。
  • 发布您的 xml 代码...
  • @rupps 你是如何让你的物品高度可变的?我需要这样的清单!
  • @AVEbrahimi,没什么特别的,只是将“包装到内容”设置为项目,但你会遇到这个问题
  • 我在getView中没有做任何奇怪的事情,只是避免发布它,因为它非常大并且充满了与这个问题无关的东西,问题只是膨胀的转换视图被重新转换到一个高度不同的新高度,在这种情况下滚动跳跃。顺便说一句,如果新单元格的大小“没有那么不同”,则滚动可以正常工作。没有布局 XML,视图是 100% 动态的。

标签: android listview scroll height adapter


【解决方案1】:

只需记住 ImageView 和 TextView 的高度,然后当您的视图被回收时,通过您的 ListAdapter 中的 getView 方法设置这些视图的高度(为此您需要扩展 BaseAdapter)。

所以你有一个包含数据的对象列表(一些文本,可能是图像 URL 等)。添加一个名为 imageHeight 的整数字段。首次加载列表项的图像时,将 ImageView 的高度保存到与该列表项关联的数据对象中的该整数字段。然后,在 ListAdapter 的 getView 中,将 ImageView 的高度设置为 imageHeight 的值。

这将使您的适配器返回具有适当高度的视图。当然,这仅在您已经知道要加载的图像/文本的高度时才有效。如果您向上滚动,这将是正确的,因为这些项目已经加载。

【讨论】:

  • 问题是,即使知道每个元素的高度,因为所有元素都有不同的高度,我不能用以前的高度做一个 setHeight() ,它肯定是不正确的(例如,回收的元素只是一条短消息,新的元素有一个 400px 高度的图像)我已经解决了这个问题,创建了几个间隔为 50px 的项目类型,所以 getItemType(position) 根据其内容高度返回一个类型。如果项目类型高度步长保持足够小(在我的情况下,我计算了 50px),则向上滚动时不会发生跳跃!
  • 好的,很高兴你解决了这个问题。但是,您的方法似乎只适用于一定数量的高度。我的建议实际上是将 ImageView/TextView 的高度保存在 data 对象中。因此,如果您有一个您自己编写的类的数据对象的 ArrayList,您可以向该类添加整数字段以记住它们,因此当需要回收它们时,只需设置 ImageView/TextView 的高度以及设置实际内容。这适用于任意高度。
  • 这是个好主意,但问题是,ListView 的内部都是一团糟:即使按照您的建议设置高度,滚动跳跃也是一样的,因为内部滚动例程期望相似(或关闭)高度。卷轴试图补偿高度差异,并通过回收前的高度与新高度之间的差异来校正位置。使用我的(hacky)方法,我保证高度差异不会超过 50 像素,Android 滚动例程似乎能够补偿。请注意,仅当新高度非常不同时才会出现问题。给旧的!
  • 好吧,我在我的应用程序中使用了这种技术,向上滚动甚至不会跳跃一个像素,因为这些视图中的内容已经加载,所以我想我会分享它,即使这是一个老问题。无论如何,我很高兴你已经解决了!
  • 我也成功使用了哈桑建议的方法,所以我确认它有效。另一个提示不一定适合 OP 的情况,但可能对其他人阅读本文有所帮助:可以为 View 设置最小高度,该高度可用于使列表项视图占用所需的空间量。例如,在我的列表中,项目视图是WebView 内的LinearLayout。在getView() 中,我将LinearLayout 的最小高度设置为等于缓存项的高度。这使得项目视图占用足够的空间,直到 WebView 加载其内容。
【解决方案2】:

尝试在getView中缓存图像(在WeakHashMap中)然后向上滚动不需要重新加载图像,这会导致丑陋的高度重新计算......

【讨论】:

    【解决方案3】:

    不要使用getView(int position, View convertView, ViewGroup parent)方法的convertView。

    每次调用 getView 时,您都必须对行进行充气。它会使滚动有点慢,但您的问题将得到解决。

    【讨论】:

    • 嗨!这确实是一个解决方案,但性能会很糟糕!这是一个通用的适配器,用的比较多,所以我负担不起,因为它会对应用产生很大的影响。
    • 糟糕的建议,你自己试过了吗?
    猜你喜欢
    • 1970-01-01
    • 2015-08-28
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 2015-05-04
    • 2019-07-18
    • 1970-01-01
    相关资源
    最近更新 更多