【问题标题】:Parallax effect on each item in a recycler view?回收站视图中每个项目的视差效果?
【发布时间】:2016-08-09 23:07:15
【问题描述】:

我正在尝试使用 Parallax 并遇到一些奇怪的错误,想知道是否有人可以为其添加一些输入。我见过的唯一有效实现视差的应用是 soundcloud。这很微妙,但每个项目都有一个图像背景,并且在您滚动时具有视差效果。

我已经创建了一个自定义 RecyclerView 来处理这个问题,这是我目前所拥有的:

public class ParallaxScrollListener extends RecyclerView.OnScrollListener {

private float scrollSpeed = 0.5f;

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);
    LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();

    int firstVisible = layoutManager.findFirstVisibleItemPosition();
    int visibleCount = Math.abs(firstVisible - layoutManager.findLastVisibleItemPosition());

    Matrix imageMatrix;
    float tempSpeed = -100;

    if (dy > 0) {
        tempSpeed = scrollSpeed;
    } else if (dy < 0) {
        tempSpeed = -scrollSpeed;
    }

    for (int i = firstVisible; i < (firstVisible + visibleCount); i++) {
        ImageView imageView = ((MyClass.MyAdapter.MyViewHolder) recyclerView.getLayoutManager().findViewByPosition(i).getTag()).image;
        if (imageView != null) {
            imageMatrix = imageView.getImageMatrix();
            imageMatrix.postTranslate(0, tempSpeed);
            imageView.setImageMatrix(imageMatrix);
            imageView.invalidate();
        }
    }
}

在我的RecyclerView 适配器的onBindView 中,我也有以下内容:

 Matrix matrix = viewHolder.image.getImageMatrix();
 matrix.postTranslate(0, 0);
 viewHolder.image.setImageMatrix(matrix);
 viewHolder.itemView.setTag(viewHolder);

最后在onViewRecycled 方法中我有以下内容:

@Override
    public void onViewRecycled(MyViewHolder viewHolder) {
        super.onViewRecycled(viewHolder);
        if (viewHolder.image != null) {
            viewHolder.image.setScaleType(ImageView.ScaleType.MATRIX);
            Matrix matrix = viewHolder.image.getImageMatrix();
            // this is set manually to show to the center
            matrix.reset();
            viewHolder.image.setImageMatrix(matrix);
        }
}

I been working with this code on Github to get the idea

所以视差有效,但我的 RecyclerView 中的视图也会移动。我在图像下方有一个 CardView,它会移动,在每个项目之间产生很大的间隙。滚动是造成这种情况的原因,上下滚动的次数越多,间隙越大,并且随着视差将图像移出边界,图像会变得更小。

我尝试在 OnScrollListener 中弄乱诸如 scrollSpeed 之类的数字,但它虽然减少了错误,但也减少了视差。

有没有人知道如何在我的RecyclerView 中的每个项目上实现无错误的视差效果?我觉得我在这方面有所进展,但仍然有很多问题,我不知道下一步是什么。

P.s 我试过查看 3rd 方库,但它们似乎都只使用像 CoordinatorLayout 这样的标题视差,我还没有发现任何只在列表中的每个项目上这样做的东西。

我希望这个问题能得到很好的讨论,即使我没有解决我的问题,因为 Parallax 似乎在 Android 中没有得到充分利用,而且几乎没有关于它的内容。

感谢您的宝贵时间,感谢您的帮助。

【问题讨论】:

  • 应该在每个视图上视差的图像是否相同?或者您是否希望/需要能够为onBindVH 中的每个项目设置它?
  • 不同的图片,所以每次都需要设置。我找到了一个库,很快就会发布我的答案。

标签: android animation android-recyclerview soundcloud parallax


【解决方案1】:

你在正确的轨道上。您必须使用 ScrollListener。此外,您必须访问 RecyclerViews LayoutManager 并遍历所有可见的项目并根据滚动的像素数量设置translateY

事情变得有点复杂,因为你不能使用recyclerView.getChildAt(pos),因为LayoutManager负责布局元素,它们在LayoutManager中的顺序可能与getChildAt(pos)不同。

所以算法基本上应该是这样的(伪代码,假设使用了LinearLayoutManager):

for (int i = layoutManager.findFirstVisibleItemPosition(); i <= layoutmanager.findLastVisibleItemPosition; i++){

   // i is the adapter position

   ViewHolder vh = recyclerView.findViewHolderForAdapterPosition(i);
   vh.imageView.setTranslationY( computedParalaxOffset ); // assuming ViewHolder has a imageView field on which you want to apply the parallax effect
}

【讨论】:

  • 感谢您的回复。这不是我已经拥有的吗?在我的滚动监听器中,我使用 LinearLayoutManager 来计算视图。使用 setTranslationY 似乎也没有做任何事情。 postTranslate 创建视差并且有效,但我的问题中仍然存在错误。
  • 你说得对,我忽略了这一点。我的错。所以你的问题基本上是如何计算computedParalaxOffset 值,对吧?
  • 我最终找到了一个能够整理所有内容的库。似乎他们需要一个我没有使用的自定义图像视图,这可能是我的问题的一部分。
【解决方案2】:

我设法让 Parallax 与这个库一起工作:https://github.com/yayaa/ParallaxRecyclerView

对于任何自己做这件事的人来说,玩起来看看它是如何工作的仍然是一件好事。

与我的代码类似的概念,但它确实有效!哈哈。

【讨论】: