回收站视图中每个项目的视差效果?
Parallax effect on each item in a recycler view?
我正在尝试使用 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 我试过查看第 3 方库,但它们似乎都只使用 header 视差,例如 CoordinatorLayout,我还没有发现任何仅在每个项目上执行此操作的库一个列表。
我希望这个问题能得到很好的讨论,即使我没有解决我的问题,因为视差在 Android 中似乎没有得到充分利用,而且几乎没有关于它的讨论。
感谢您的宝贵时间,感谢您的帮助。
你走在正确的轨道上。您必须使用 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
}
我设法让 Parallax 使用这个库:https://github.com/yayaa/ParallaxRecyclerView
对于自己动手做的人来说,玩一玩看看效果如何仍然是一件好事。
与我的代码类似的概念,但它确实有效!哈哈
我正在尝试使用 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 我试过查看第 3 方库,但它们似乎都只使用 header 视差,例如 CoordinatorLayout,我还没有发现任何仅在每个项目上执行此操作的库一个列表。
我希望这个问题能得到很好的讨论,即使我没有解决我的问题,因为视差在 Android 中似乎没有得到充分利用,而且几乎没有关于它的讨论。
感谢您的宝贵时间,感谢您的帮助。
你走在正确的轨道上。您必须使用 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
}
我设法让 Parallax 使用这个库:https://github.com/yayaa/ParallaxRecyclerView
对于自己动手做的人来说,玩一玩看看效果如何仍然是一件好事。
与我的代码类似的概念,但它确实有效!哈哈