【问题标题】:View flicking on slow scroll of Android RecyclerViewAndroid RecyclerView 慢滚动上的视图闪烁
【发布时间】:2021-02-18 10:07:03
【问题描述】:

我在回收站视图顶部有一个水平线性布局,如果 findFirstCompletelyVisibleItemPosition > 2 并且如果 findFirstCompletelyVisibleItemPosition

我能够在回收站视图上使用滚动侦听器来实现这一点。但是有一个问题,当您滚动慢速视图时,它会闪烁(快速显示和隐藏)。但是,如果我们在回收站视图上快速滚动,这会很好。

这是我的代码

recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {

        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)

            val findFirstCompletelyVisibleItemPosition =
                layoutManager.findFirstCompletelyVisibleItemPosition()

            if (findFirstCompletelyVisibleItemPosition > 2) {
                layout.visibility = View.GONE
            } else {
                layout.visibility = View.VISIBLE
            }

        }
    })

【问题讨论】:

  • 你的LinearLayoutRecyclerView里面的项目的一部分还是只是放在上面?
  • 它放在它上面。由于它周围的某些逻辑,它不能成为 RecyclerView 的一部分。

标签: android android-recyclerview android-linearlayout


【解决方案1】:

经过一番修改,这就是我想出的。由于轻微的性能影响,这不是最漂亮的解决方案,但它应该可以解决问题。

因为您的LinearLayout 应该在滚动期间更改其可见性,而不仅仅是在滚动完成时,我们必须坚持使用onScrolled。虽然此方法确实提供了完成的滚动量(dxdy),但它以像素为单位提供(似乎,我做了一些测试)。这意味着我们必须将其转换为 dp 才能真正从该值中获得一些用途,这可能太昂贵而无法在每次调用该方法时进行。

相反,我决定将findFirstCompletelyVisibleItemPosition 的最后几个值保存在一个数组中。然后每次onScrolled 运行时都会检查这个数组。它将查找低于您的目标值 2 的项目。您的 LinearLayout 只有在没有找到小于 2 的值时才会显示。 这会产生一个更可用且更一致的 truefalse 值,不应再导致闪烁。

以下是实现此行为的代码:

recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        val layoutManager = recyclerView.layoutManager as LinearLayoutManager // TODO: unchecked cast

        val prevValues = IntArray(5) // this can be changed to increase performance
        var counter = 0

        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)

            prevValues[counter++] = layoutManager.findFirstCompletelyVisibleItemPosition()

            if(counter == prevValues.size)
                counter = 0

            var smallerValueFound = false
            for(prevValue in prevValues.indices) {
                if(prevValue < 2) {
                    smallerValueFound = true
                    break
                }
            }

            if(smallerValueFound) layout.visibility = View.GONE
            else layout.visibility = View.VISIBLE
        }
})

为了减少性能损失,您只能在onScrolled 运行时访问该阵列,尽管这本身可能会出现问题。您还可以减小数组的大小。

【讨论】:

  • 感谢您的解决方案。试过了,还是有闪烁效果。
  • 隐藏布局是否会导致RecyclerView 改变其大小?
  • 是的。 RecyclerView 高度发生变化
  • 那么问题应该很明显了。当您的 RecyclerView 更改其大小时,顶部有更多空间用于放置项目。这将填充第二个以上的项目。但是,这会导致您的布局再次可见,这意味着第二个项目再次位于顶部。这将导致布局再次被隐藏,开始一个循环。你需要一些方法来检测这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-27
  • 2016-07-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多