RecyclerView& SnapHelper - >获取快照/定位视图

时间:2016-10-30 22:19:01

标签: android android-recyclerview

我最近开始使用SnapHelper中提供的Support Library v24,以便与 Google Play商店中的水平RecyclerView非常相似。< / p>

我的问题很简单。

使用RecyclerView.OnScrollListener我可以在滚动状态为设置时收到通知(非常类似于ViewPager.OnPageChangedListener。这很重要,因为当滚动定居时,我需要为LinearSnapHelper的默认行为居中的视图设置动画。该动画显示焦点将转移到即将成为焦点的项目

现在,我设法通过以下行获得滚动状态空闲时居中的视图:

final int centered = (llm.findLastCompletelyVisibleItemPosition() - llm.findFirstCompletelyVisibleItemPosition())  / 2 + llm.findFirstVisibleItemPosition();  // where llm is my LinearLayoutManager

问题是,当滚动完成时启动动画很奇怪:当滚动停止时我真的需要平滑地播放动画,这样当滚动空闲时,动画也会完成。

正如您所看到的,我很难找到RecyclerView中哪一项将是居中的。

以下是我到目前为止尝试的解决方案。

  1. 当滚动状态设置为RecyclerView.SCROLL_STATE_SETTLING时,我尝试使用相同的计算。不幸的是,当滚动不空闲时从适配器调用findVisiblePosition方法是一个坏主意:根据滚动速度,当调用这些所谓的方法时,可见项可能不完全相同滚动完成时。实际上它会告诉我在通话时哪些物品是可见的。这完全有道理,但我需要尝试找出它......

  2. 我尝试扩展 LinearSnapHelper,以便在调用onFling(...)时我可以使用findSnapView(...)来获取 snapped 或使用findTargetSnapPosition(...)希望在滚动完成时告诉我哪个视图居中;

  3. 当滚动状态为RecyclerView.SCROLL_STATE_SETTLING时,我也尝试使用findSnapView(...)

  4. 在所有这些解决方案中,没有一个通过多次测试(尝试不同的滑动强度和速度)。有些人在一些情况下做对了,但在不同情况下弄错了,因此解决方案无法使用。

    查看LinearSnapHelper内部我认为我开始明白,不知何故,在滑动之后,此类会在滚动完成之前根据需要多次计算总滚动并捕捉视图(距离的数量)滚动)因此知道哪个视图将是最终捕捉视图 ...除非我把它弄错了因为snapped不居中?

    无论如何,我的主要问题是:无论速度和力度如何,我怎样才能知道我的RecyclerView哪个项目会在刷卡后居中?

4 个答案:

答案 0 :(得分:5)

编辑:

正如少数人所指出的那样,这是不可靠的,特别是当快速滑动而不是甩尾时发生快照时。

我建议您使用RecyclerView.OnScrollListener,并在RecyclerView'已确定'后检查位置。这里有一个很好的教程

https://medium.com/over-engineering/detecting-snap-changes-with-androids-recyclerview-snaphelper-9e9f5e95c424

上一个回答:

您需要继承SnapHelper并覆盖findTargetSnapPosition。由super.findTargetSnapPosition(layoutManager, velocityX, velocityY)计算的位置是您RecyclerView即将捕捉到的位置。

SnapHelper snapHelper = new LinearSnapHelper() {
    @Override
    public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
        int snapPosition = super.findTargetSnapPosition(layoutManager, velocityX, velocityY);

        // Do something with snapPosition

        return snapPosition;
    }
};

答案 1 :(得分:0)

如果您使用LinearSnapHelper,则有LinearSnapHelper#findTargetSnapPosition方法。它返回要捕捉的视图的适配器位置。

答案 2 :(得分:0)

滚动结算后,您可以使用layoutManager.findFirstCompletelyVisibleItemPosition()

答案 3 :(得分:0)

我有一个水平的 Recycler View ,看看 layoutManager :

 val layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, true)

     val snapHelper: SnapHelper = PagerSnapHelper()
                snapHelper.attachToRecyclerView(recyclerView)
     

您可以使用 findLastCompletelyVisibleItemPosition 来查找位置

 recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
                override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                    super.onScrolled(recyclerView, dx, dy)
                    val visiblePosition = layoutManager.findLastCompletelyVisibleItemPosition()
                    if (visiblePosition >= 0) {
                      //do somthing with item position
                  
                    }
                }
            })