我有一个带图片的 RecyclerView,它基于这个方案。使用 Glide 懒加载图像进入视图。我需要添加类似于这个示例中居中图片的缩放效果:
我该如何实现呢?
我有一个带图片的 RecyclerView,它基于这个方案。使用 Glide 懒加载图像进入视图。我需要添加类似于这个示例中居中图片的缩放效果:
我该如何实现呢?
影响您想要的内容最直接的方法是扩展LinearLayoutManager
。正如您无疑已经发现的那样,正确地连接滚动事件是很麻烦的:
因此,让我们扩展这个管理器。我们将创建一些您可能想要公开的参数。
public class ZoomCenterCardLayoutManager extends LinearLayoutManager {
// Shrink the cards around the center up to 50%
private final float mShrinkAmount = 0.5f;
// The cards will be at 50% when they are 75% of the way between the
// center and the edge.
private final float mShrinkDistance = 0.75f;
填写你的构造函数,然后重写 scrollHorizontallyBy
:
@Override
public int scrollHorizontallyBy(int dx,
RecyclerView.Recycler recycler, RecyclerView.State state) {
调用父类的版本并保存已行进的距离。在方法结束时需要返回此距离:
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;
}
这几乎是您所需的全部内容。最后一步是确保在初始化之后调用此调整,否则缩放将不会生效,直到第一次移动控件为止:
@Override
public void onLayoutChildren(Recycler recycler, State state) {
super.onLayoutChildren(recycler, state);
scrollHorizontallyBy(0, recycler, state);
}
}
就是这样。非常灵敏,您可以将此新布局管理器放入任何水平回收器中。
float scale = interp(Math.abs(myMidpoint - recyclerMidpoint));
interp
是什么? - Andrey Rankov