Estoy creando un carrusel horizontal RecyclerView con zoom sobre el punto enfocado que está empezando desde el primer elemento de la RecyclerView.
Código de CenterZoomLayoutManager personalizado:
public class CenterZoomLayoutManager extends LinearLayoutManager {
private final float mShrinkAmount = 0.15f;
private final float mShrinkDistance = 0.9f;
public CenterZoomLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@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;
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
scrollHorizontallyBy(0, recycler, state);
}
}
Y en mi Fragment
, tengo el siguiente:
private void onSetRecyclerView() {
recyclerView = fragmentView.findViewById(R.id.recyclerView);
if (recyclerView != null) {
RecyclerView.LayoutManager layoutManager = new CenterZoomLayoutManager(context, LinearLayoutManager.HORIZONTAL,
false);
recyclerView.scrollToPosition(storeList.size() / 2);
final SnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
}
Quiero empezar mi RecyclerView desde el punto central y no desde la posición de inicio.
Culpable:
en mi CenterZoomLayoutManager
, estoy estableciendo el píxel de inicio de compensación a 0 píxeles a través scrollHorizontallyBy(0, recycler, state)
.
Problema:
No puedo encontrar una manera de pasar los píxeles de desplazamiento creados por recyclerView.scrollToPosition(storeList.size() / 2)
el CenterZoomLayoutManager
. Traté de buscar diferentes incorporado en el método para obtener el X-offset, pero hasta ahora sin suerte.
La solución es cambiar el tiempo de cuando LinearSnapHelper
está unido al RecyclerView
. El siguiente es un vuelto a trabajar onSetRecyclerView()
que se ajustará el elemento central de la RecyclerView
del centro de la pantalla. Tenga en cuenta que el LinearSnapHelper
no está conectada hasta que el RecyclerView
se presenta y volutas de manera apropiada. No es necesario hacer ningún desplazamiento en onLayoutChildren()
.
private void onSetRecyclerView() {
recyclerView = findViewById(R.id.recyclerView);
CenterZoomLayoutManager layoutManager =
new CenterZoomLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
// Scroll to the position we want to snap to
layoutManager.scrollToPosition(storeList.size() / 2);
// Wait until the RecyclerView is laid out.
recyclerView.post(new Runnable() {
@Override
public void run() {
// Shift the view to snap near the center of the screen.
// This does not have to be precise.
int dx = (recyclerView.getWidth() - recyclerView.getChildAt(0).getWidth()) / 2;
recyclerView.scrollBy(-dx, 0);
// Assign the LinearSnapHelper that will initially snap the near-center view.
LinearSnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
}
});
}
Así es como aparece la pantalla inicial de mi aplicación de prueba. Hay 201 "tiendas".