android - item - Desplácese hacia RecyclerView para mostrar el elemento seleccionado en la parte superior
recyclerview scroll to position (14)
// Elemento de desplazamiento pos
linearLayoutManager.scrollToPositionWithOffset(pos, 0);
Estoy buscando una manera de desplazar un
RecyclerView
para mostrar el elemento seleccionado en la parte superior.
En un
ListView
pude hacer eso usando
scrollTo(x,y)
y obteniendo la parte superior del elemento que necesita ser centrado.
Algo como:
@Override
public void onItemClick(View v, int pos){
mylistView.scrollTo(0, v.getTop());
}
El problema es que
RecyclerView
devuelve un error al usar su método
scrollTo
diciendo
RecyclerView no admite el desplazamiento a una posición absoluta
¿Cómo puedo desplazar un
RecyclerView
para colocar el elemento seleccionado en la parte superior de la vista?
En mi caso, mi
RecyclerView
tiene una parte superior acolchada como esta
<android.support.v7.widget.RecyclerView
...
android:paddingTop="100dp"
android:clipToPadding="false"
/>
Luego, para desplazar un elemento hacia arriba, necesito
recyclerViewLinearLayoutManager.scrollToPositionWithOffset(position, -yourRecyclerView.getPaddingTop());
Lo que hice para restaurar la posición de desplazamiento después de actualizar el RecyclerView al hacer clic en el botón:
if (linearLayoutManager != null) {
index = linearLayoutManager.findFirstVisibleItemPosition();
View v = linearLayoutManager.getChildAt(0);
top = (v == null) ? 0 : (v.getTop() - linearLayoutManager.getPaddingTop());
Log.d("TAG", "visible position " + " " + index);
}
else{
index = 0;
}
linearLayoutManager = new LinearLayoutManager(getApplicationContext());
linearLayoutManager.scrollToPositionWithOffset(index, top);
obtener el desplazamiento del primer elemento visible desde la parte superior antes de crear el objeto linearLayoutManager y después de instanciarlo, se llamó al scrollToPositionWithOffset del objeto LinearLayoutManager.
Ninguna de las respuestas explica cómo mostrar los últimos elementos en la parte superior.
Por lo tanto, las respuestas funcionan solo para elementos que todavía tienen suficientes elementos encima o debajo de ellos para llenar el
RecyclerView
restante.
Por ejemplo, si hay 59 elementos y se selecciona un 56º elemento, debe estar en la parte superior como en la imagen a continuación:
Podríamos manejar esos casos usando
linearLayoutManager.scrollToPositionWithOffset(pos, 0)
y una lógica adicional en el
Adapter
de
RecyclerView
, agregando un margen personalizado debajo del último elemento (si el último elemento no es visible, significa que hay suficiente espacio para llenar el
RecyclerView
)
El margen personalizado podría ser una diferencia entre la altura de la vista raíz y la altura del elemento.
Entonces, su
Adapter
para
RecyclerView
se vería de la siguiente manera:
View firstView = mRecyclerView.getChildAt(0);
int toY = firstView.getTop();
int firstPosition = mRecyclerView.getChildAdapterPosition(firstView);
View thisView = mRecyclerView.getChildAt(thisPosition - firstPosition);
int fromY = thisView.getTop();
mRecyclerView.smoothScrollBy(0, fromY - toY);
No sé por qué no encontré la mejor respuesta, pero es realmente simple.
recyclerView.smoothScrollToPosition(position);
Sin errores
Crea animaciones
Prueba lo que funcionó para mí genial!
Crear una variable
private static int displayedposition = 0;
Ahora para la posición de su RecyclerView en su actividad.
myRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
LinearLayoutManager llm = (LinearLayoutManager) myRecyclerView.getLayoutManager();
displayedposition = llm.findFirstVisibleItemPosition();
}
});
Coloque esta declaración donde desee que coloque el sitio anterior que se muestra en su vista.
LinearLayoutManager llm = (LinearLayoutManager) mRecyclerView.getLayoutManager();
llm.scrollToPositionWithOffset(displayedposition , youList.size());
Bueno, eso es todo, funcionó bien para mí
Si está buscando LinearLayout Manager vertical, puede lograr un desplazamiento suave utilizando un
LinearSmoothScroller
personalizado:
import android.content.Context;
import android.graphics.PointF;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.RecyclerView;
public class SnappingLinearLayoutManager extends LinearLayoutManager {
public SnappingLinearLayoutManager(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 SnappingLinearLayoutManager.this
.computeScrollVectorForPosition(targetPosition);
}
@Override
protected int getVerticalSnapPreference() {
return SNAP_TO_START;
}
}
}
use una instancia del layoutmanager en la vista de reciclaje y luego llame a
recyclerView.smoothScrollToPosition(pos);
se desplazará suavemente a la posición seleccionada a la parte superior de la vista del reciclador
Si está utilizando
LinearLayoutManager
o Staggered
GridLayoutManager
, cada uno tiene un método
scrollToPositionWithOffset
que toma tanto la posición como el desplazamiento del inicio del elemento desde el inicio de
RecyclerView
, que parece que lograría lo que necesita (configurando el el desplazamiento a 0 debe alinearse con la parte superior).
Por ejemplo:
//Scroll item 2 to 20 pixels from the top
linearLayoutManager.scrollToPositionWithOffset(2, 20);
Solo necesita llamar a
recyclerview.scrollToPosition(position)
.
¡Esta bien!
Si desea llamarlo en el adaptador, simplemente deje que su adaptador tenga la instancia de recyclerview o la actividad o fragmento que contiene recyclerview, que implementa el método
getRecyclerview()
en ellos.
Espero que te pueda ayudar.
Utilizo el siguiente código para desplazar suavemente un elemento (thisView) hacia la parte superior.
Funciona también para GridLayoutManager con vistas de diferentes alturas:
View firstView = mRecyclerView.getChildAt(0); int toY = firstView.getTop(); int firstPosition = mRecyclerView.getChildAdapterPosition(firstView); View thisView = mRecyclerView.getChildAt(thisPosition - firstPosition); int fromY = thisView.getTop(); mRecyclerView.smoothScrollBy(0, fromY - toY);
Parece funcionar lo suficientemente bien como para una solución rápida.
desplazarse en una posición particular
y esto me ayudó mucho.
por clic oyente puede obtener la posición en su adaptador
layoutmanager.scrollToPosition(int position);
lo mismo con el regulador de velocidad
public class SmoothScrollLinearLayoutManager extends LinearLayoutManager {
private static final float MILLISECONDS_PER_INCH = 110f;
private Context mContext;
public SmoothScrollLinearLayoutManager(Context context,int orientation, boolean reverseLayout) {
super(context,orientation,reverseLayout);
mContext = context;
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
int position) {
RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext()){
//This controls the direction in which smoothScroll looks for your view
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return new PointF(0, 1);
}
//This returns the milliseconds it takes to scroll one pixel.
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
}
};
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
private class TopSnappedSmoothScroller extends LinearSmoothScroller {
public TopSnappedSmoothScroller(Context context) {
super(context);
}
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return SmoothScrollLinearLayoutManager.this
.computeScrollVectorForPosition(targetPosition);
}
@Override
protected int getVerticalSnapPreference() {
return SNAP_TO_START;
}
}
}
simplemente llame a este método simplemente:
((LinearLayoutManager)recyclerView.getLayoutManager()).scrollToPositionWithOffset(yourItemPosition,0);
en lugar de:
recyclerView.scrollToPosition(yourItemPosition);
If you want to scroll automatic without show scroll motion then you need to write following code:
**=> mRecyclerView.getLayoutManager().scrollToPosition(position);**
If you want to display scroll motion then you need to add following code.
=>Step 1: You need to declare SmoothScroller.
RecyclerView.SmoothScroller smoothScroller = new
LinearSmoothScroller(this.getApplicationContext()) {
@Override
protected int getVerticalSnapPreference() {
return LinearSmoothScroller.SNAP_TO_START;
}
};
=>step 2: You need to add this code any event you want to perform scroll to specific position.
=>First you need to set target position to SmoothScroller.
**smoothScroller.setTargetPosition(position);**
=>Then you need to set SmoothScroller to LayoutManager.
**mRecyclerView.getLayoutManager().startSmoothScroll(smoothScroller);**