android - seleccionar - RecyclerView: ¿cómo deslizar suavemente hasta la parte superior del elemento en una determinada posición?
recyclerview seleccionar item (8)
Anule la función CalculateDyToMakeVisible / CalculateDxToMakeVisible en LinearSmoothScroller para implementar la posición de desplazamiento Y / X
override fun calculateDyToMakeVisible(view: View, snapPreference: Int): Int {
return super.calculateDyToMakeVisible(view, snapPreference) - ConvertUtils.dp2px(10f)
}
En un RecyclerView, puedo desplazarme repentinamente a la parte superior de un elemento seleccionado usando:
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(position, 0);
Sin embargo, esto mueve abruptamente el artículo a la posición superior. Quiero pasar a la parte superior de un elemento sin problemas .
También he intentado:
recyclerView.smoothScrollToPosition(position);
pero no funciona bien, ya que no mueve el elemento a la posición seleccionada en la parte superior. Simplemente desplaza la lista hasta que el elemento en la posición sea visible.
Esta es una extensión de funciones que escribí en Kotlin para llamar directamente en RecyclerView (basado en la respuesta de @Paul Woitaschek):
fun RecyclerView.smoothSnapToPosition(position: Int, snapMode: Int = LinearSmoothScroller.SNAP_TO_START) {
val smoothScroller = object: LinearSmoothScroller(this.context) {
override fun getVerticalSnapPreference(): Int {
return snapMode
}
override fun getHorizontalSnapPreference(): Int {
return snapMode
}
}
smoothScroller.targetPosition = position
layoutManager?.startSmoothScroll(smoothScroller)
}
Úselo así:
myRecyclerView.smoothSnapToPosition(itemPosition)
La forma más fácil que he encontrado para desplazar un
RecyclerView
es la siguiente:
// Define the Index we wish to scroll to.
final int lIndex = 0;
// Assign the RecyclerView''s LayoutManager.
this.getRecyclerView().setLayoutManager(this.getLinearLayoutManager());
// Scroll the RecyclerView to the Index.
this.getLinearLayoutManager().smoothScrollToPosition(this.getRecyclerView(), new RecyclerView.State(), lIndex);
Podemos intentar así
recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView,new RecyclerView.State(), recyclerView.getAdapter().getItemCount());
Probablemente el enfoque @droidev sea el correcto, pero solo quiero publicar algo un poco diferente, que básicamente hace el mismo trabajo y no requiere la extensión del LayoutManager.
Una NOTA aquí: esto funcionará bien si su elemento (el que desea desplazar en la parte superior de la lista) está visible en la pantalla y solo desea desplazarlo hacia la parte superior automáticamente. Es útil cuando el último elemento de su lista tiene alguna acción, que agrega nuevos elementos en la misma lista y desea enfocar al usuario en los nuevos elementos agregados:
int recyclerViewTop = recyclerView.getTop();
int positionTop = recyclerView.findViewHolderForAdapterPosition(positionToScroll) != null ? recyclerView.findViewHolderForAdapterPosition(positionToScroll).itemView.getTop() : 200;
final int calcOffset = positionTop - recyclerViewTop;
//then the actual scroll is gonna happen with (x offset = 0) and (y offset = calcOffset)
recyclerView.scrollBy(0, offset);
La idea es simple: 1. Necesitamos obtener la coordenada superior del elemento de vista del reciclador; 2. Necesitamos obtener la coordenada superior del elemento de vista que queremos desplazar hacia arriba; 3. Al final con el desplazamiento calculado tenemos que hacer
recyclerView.scrollBy(0, offset);
200 es solo un valor entero codificado de ejemplo que puede usar si el elemento del marcador no existe, porque eso también es posible.
Solía así:
recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, new RecyclerView.State(), 5);
para esto tienes que crear un LayoutManager personalizado
public class LinearLayoutManagerWithSmoothScroller extends LinearLayoutManager {
public LinearLayoutManagerWithSmoothScroller(Context context) {
super(context, VERTICAL, false);
}
public LinearLayoutManagerWithSmoothScroller(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
int position) {
RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext());
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
private class TopSnappedSmoothScroller extends LinearSmoothScroller {
public TopSnappedSmoothScroller(Context context) {
super(context);
}
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return LinearLayoutManagerWithSmoothScroller.this
.computeScrollVectorForPosition(targetPosition);
}
@Override
protected int getVerticalSnapPreference() {
return SNAP_TO_START;
}
}
}
use esto para su RecyclerView y llame a smoothScrollToPosition.
ejemplo:
recyclerView.setLayoutManager(new LinearLayoutManagerWithSmoothScroller(context));
recyclerView.smoothScrollToPosition(position);
esto se desplazará hasta la parte superior del elemento RecyclerView de la posición especificada.
espero que esto ayude.
RecyclerView
está diseñado para ser extensible, por lo que no es necesario subclasificar el
LayoutManager
(como
sugirió droidev
) solo para realizar el desplazamiento.
En su lugar, solo cree un
SmoothScroller
con la preferencia
SNAP_TO_START
:
RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(context) {
@Override protected int getVerticalSnapPreference() {
return LinearSmoothScroller.SNAP_TO_START;
}
};
Ahora establece la posición a la que desea desplazarse:
smoothScroller.setTargetPosition(position);
y pasa ese SmoothScroller al LayoutManager:
layoutManager.startSmoothScroll(smoothScroller);