Actualización de Google I / O 2019
¡ViewPager2 ya está aquí!
Google acaba de anunciar en la charla 'Novedades de Android' (también conocido como 'La nota clave de Android') que están trabajando en un nuevo ViewPager basado en RecyclerView.
De las diapositivas:
Como ViewPager, pero mejor
- Fácil migración desde ViewPager
- Basado en RecyclerView
- Soporte de modo de derecha a izquierda
- Permite la paginación vertical
- Notificaciones de cambio de conjunto de datos mejoradas
Puede consultar la última versión aquí y las notas de la versión aquí . También hay una muestra oficial .
Opinión personal: Creo que esta es una adición realmente necesaria. Recientemente tuve muchos problemas con la PagerSnapHelper
oscilación de izquierda a derecha indefinidamente ; vea el boleto que abrí.
Nueva respuesta (2016)
Ahora puede usar SnapHelper .
Si desea un comportamiento de ajuste alineado al centro similar a ViewPager , use PagerSnapHelper :
SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
También hay un LinearSnapHelper . Lo he probado y si arrojas con energía, se desplaza 2 elementos con 1 lanzamiento. Personalmente, no me gustó, pero solo decide tú mismo: intentarlo solo lleva unos segundos.
Respuesta original (2016)
Después de muchas horas de probar 3 soluciones diferentes que se encuentran aquí en SO, finalmente construí una solución que imita muy de cerca el comportamiento encontrado en un ViewPager
.
La solución se basa en la solución @eDizzle , que creo que he mejorado lo suficiente como para decir que funciona casi como un ViewPager
.
Importante: el RecyclerView
ancho de mis artículos es exactamente el mismo que el de la pantalla. No lo he probado con otros tamaños. También lo uso con una horizontal LinearLayoutManager
. Creo que necesitará adaptar el código si desea un desplazamiento vertical.
Aquí tienes el código:
public class SnappyRecyclerView extends RecyclerView {
public SnappyRecyclerView(Context context) {
super(context);
}
public SnappyRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public SnappyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean fling(int velocityX, int velocityY) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
int leftMargin = (screenWidth - lastView.getWidth()) / 2;
int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
int leftEdge = lastView.getLeft();
int rightEdge = firstView.getRight();
int scrollDistanceLeft = leftEdge - leftMargin;
int scrollDistanceRight = rightMargin - rightEdge;
if (Math.abs(velocityX) < 1000) {
if (leftEdge > screenWidth / 2) {
smoothScrollBy(-scrollDistanceRight, 0);
} else if (rightEdge < screenWidth / 2) {
smoothScrollBy(scrollDistanceLeft, 0);
} else {
if (velocityX > 0) {
smoothScrollBy(-scrollDistanceRight, 0);
} else {
smoothScrollBy(scrollDistanceLeft, 0);
}
}
return true;
} else {
if (velocityX > 0) {
smoothScrollBy(scrollDistanceLeft, 0);
} else {
smoothScrollBy(-scrollDistanceRight, 0);
}
return true;
}
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
if (state == SCROLL_STATE_IDLE) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
int leftMargin = (screenWidth - lastView.getWidth()) / 2;
int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
int leftEdge = lastView.getLeft();
int rightEdge = firstView.getRight();
int scrollDistanceLeft = leftEdge - leftMargin;
int scrollDistanceRight = rightMargin - rightEdge;
if (leftEdge > screenWidth / 2) {
smoothScrollBy(-scrollDistanceRight, 0);
} else if (rightEdge < screenWidth / 2) {
smoothScrollBy(scrollDistanceLeft, 0);
}
}
}
}
¡Disfrutar!