I have RecyclerView with images. It based on this solution. Images are lazy loaded into view with Glide. I need to add zoom on central image like in this:
How can i do it?
The most direct way to affect what you want is to extend LinearLayoutManager
.
As you've no doubt discovered, hooking into the scroll events properly is a pain:
So let's extend the manager. We'll create a few parameters that you might expose.
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;
Fill out your constructors, and then override scrollHorizontallyBy
:
@Override
public int scrollHorizontallyBy(int dx,
RecyclerView.Recycler recycler, RecyclerView.State state) {
Call the parent's version and save the distance travelled. We'll need to return this at the end of the method:
int scrolled = super.scrollHorizontallyBy(dx, recycler, state);
We are going to set up a simple linear interpolation. It looks nice enough.
float midpoint = getWidth() / 2.f;
float d0 = 0.f;
float d1 = mShrinkDistance * midpoint;
float s0 = 1.f;
float s1 = 1.f - mShrinkAmount;
Loop through all of the active children of the control, run the interpolation, and set the scale of the child.
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;
}
This is almost all you need. One final step is to make sure that this adjustment is called after initialization -- otherwise the zooming won't take effect until the first time the control is moved:
@Override
public void onLayoutChildren(Recycler recycler, State state) {
super.onLayoutChildren(recycler, state);
scrollHorizontallyBy(0, recycler, state);
}
}
And that's all there is to it. Super responsive, and you can drop this new layout manager into any horizontal recycler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With