Recycler视图 – 滚动时调整项目视图的大小(对于旋转木马效果)

我需要创建一个垂直的Recyclerview,其中应调整屏幕中心的项目视图,以便在滚动时具有缩放效果。

我尝试但没有奏效的事情:

  1. 添加滚动侦听器并按位置循环浏览项目视图,测量居中位置,然后更新居中view LayoutParams

    • RecyclerView不会在滚动时计算项目的位置或更新视图。 如果在onScrolled中执行此类操作,则抛出IllegalStateException
  2. 在滚动状态下更改onScrollStateChanged中居中项目视图的LayoutParamsIDLESETTLING

    • 仅在滚动已经/将要完成之后才更新视图,而不是在滚动项目期间执行。
  3. 剩下的最后一个选项是实现自定义的LayoutManager ,它将扩展默认的LayoutManager

    • 据我所知,实现自定义Layoutmanager涉及处理需要处理的更复杂的计算。

任何其他解决方案或想法将不胜感激。

Related of "Recycler视图 – 滚动时调整项目视图的大小(对于旋转木马效果)"

我在SO上find了这个答案 ,它在横向上做了完全相同的事情。 Answer提供了一个扩展LinearLayoutManager的工作解决方案。 我修改它有点适应垂直列表,它的工作原理。 如果实施中有任何错误,请在评论中告诉我。 干杯!

自定义布局管理器

 public class CenterZoomLayoutManager extends LinearLayoutManager { private final float mShrinkAmount = 0.15f; private final float mShrinkDistance = 0.9f; public CenterZoomLayoutManager(Context context) { super(context); } public CenterZoomLayoutManager(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); } @Override public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { int orientation = getOrientation(); if (orientation == VERTICAL) { int scrolled = super.scrollVerticallyBy(dy, recycler, state); float midpoint = getHeight() / 2.f; float d0 = 0.f; float d1 = mShrinkDistance * midpoint; float s0 = 1.f; float s1 = 1.f - mShrinkAmount; for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); float childMidpoint = (getDecoratedBottom(child) + getDecoratedTop(child)) / 2.f; float d = Math.min(d1, Math.abs(midpoint - childMidpoint)); float scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0); child.setScaleX(scale); child.setScaleY(scale); } return scrolled; } else { return 0; } } @Override public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { int orientation = getOrientation(); if (orientation == HORIZONTAL) { int scrolled = super.scrollHorizontallyBy(dx, recycler, state); float midpoint = getWidth() / 2.f; float d0 = 0.f; float d1 = mShrinkDistance * midpoint; float s0 = 1.f; float s1 = 1.f - mShrinkAmount; for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); float childMidpoint = (getDecoratedRight(child) + getDecoratedLeft(child)) / 2.f; float d = Math.min(d1, Math.abs(midpoint - childMidpoint)); float scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0); child.setScaleX(scale); child.setScaleY(scale); } return scrolled; } else { return 0; } } } 

水平方向: 在此处输入图像描述

垂直方向:

在此处输入图像描述