En un RecyclerView, soy capaz de repente desplácese hasta la parte superior de un elemento seleccionado mediante el uso de:

((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(position, 0);

Sin embargo, este abruptamente mueve el elemento a la posición superior. Quiero mover a la parte superior de un elemento suavemente.

También he intentado:

recyclerView.smoothScrollToPosition(position);

pero no funciona bien ya que no mover el elemento a la posición seleccionada en la parte superior. Simplemente se desplaza por la lista hasta que el elemento en la posición es visible.

InformationsquelleAutor Tiago | 2015-07-05

8 Comentarios

  1. 167

    RecyclerView está diseñado para ser extensible, por lo que no hay necesidad de crear una subclase de la LayoutManager (como droidev sugerido) sólo para realizar el desplazamiento.

    Lugar, sólo tienes que crear una SmoothScroller con la preferencia SNAP_TO_START:

    RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(context) {
      @Override protected int getVerticalSnapPreference() {
        return LinearSmoothScroller.SNAP_TO_START;
      }
    };

    Ahora definir la posición donde desea desplazarse a:

    smoothScroller.setTargetPosition(position);

    y de paso que SmoothScroller para el LayoutManager:

    layoutManager.startSmoothScroll(smoothScroller);
    • Gracias por este corto solución. Sólo dos cosas más que tenía que tener en cuenta en mi aplicación: Como tengo un desplazamiento horizontal de la vista, yo tenía que dar protected int getHorizontalSnapPreference() { return LinearSmoothScroller.SNAP_TO_START; }. Además tuve que implementar el método abstracto public PointF computeScrollVectorForPosition(int targetPosition) { return layoutManager.computeScrollVectorForPosition(targetPosition); }.
    • no es abstracto. También devuelve layoutManager.computeScrollVectorForPosition por defecto.
    • Bien. Estoy desafortunadamente el uso de la v7 de la biblioteca de soporte 23.4.0. Esto debe haber sido cambiado en una versión posterior.
    • RecyclerView puede ser diseñado para ser extensible, pero una cosa tan simple como esta sólo se siente perezoso que falta. Buena respuesta tho! Gracias.
    • Hay alguna forma de dejarlo complemento para empezar, pero con un desplazamiento de X dp?
    • no podía este enfoque crear problemas? Quiero decir, el código estoy seguro de que va a funcionar, pero básicamente lo que estamos sugiriendo a la derivación de la RecyclerView smoothScrollToPosition() y en lugar de llamar al desplazarse directamente a través del gestor de diseño, por lo que cualquier comprobación interna potencialmente hecho por smoothScrollToPosition() se pierde. Android docs estado en su lugar: «RecyclerView.LayoutManager es responsable de la creación del desplazamiento real de la acción. Si desea proporcionar una costumbre desplazamiento suave lógica, reemplazar smoothScrollToPosition(RecyclerView, Estado, int) en su LayoutManager.»
    • exactamente, esto va a romper RecyclerView predeterminado de smoothScrollToPosition funcionalidad
    • ¿Cómo puedo saber cuándo mostrar el botón para Desplazarse a la parte superior mediante recyclerView.addOnScrollListener ?
    • es posible ralentizar su velocidad?
    • es trabajo, pero quiero dejar elemento en el centro como he horizontal recyclerview y un máximo de 3 elementos son visibles en la pantalla.así que cuando hice clic sobre cualquier otro asunto que quiero que el elemento de en medio/centro de cómo hacerlo?

  2. 106

    para ello tienes que crear un custom LayoutManager

    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;
            }
        }
    }

    usar esto para su RecyclerView y llame a smoothScrollToPosition.

    ejemplo :

     recyclerView.setLayoutManager(new LinearLayoutManagerWithSmoothScroller(context));
     recyclerView.smoothScrollToPosition(position);

    esto va a desplazarse a la parte superior de la RecyclerView elemento de la posición especificada.

    espero que esto ayude.

    • Tuve problemas en la implementación de la propuesta de LayoutManager. Esta respuesta aquí trabajado mucho más fácil para mí: stackoverflow.com/questions/28025425/…
    • Sólo respuesta útil después de las horas de dolor, esto funciona como fue diseñado!
    • El SNAP_TO_START hacer el truco! Tks!
    • He usado el ejemplo y con desplazamiento suave y generalmente SNAP_TO_START es lo que necesito, pero funciona con algunos problemas por mí. A veces el desplazamiento se detiene 1,2,3 o 4 posiciones antes de que me pase a smoothScrollToPosition. ¿Por qué este problema puede producirse? Gracias.
    • se puede de alguna manera llegar a su código a nosotros ? Estoy bastante seguro de que es su código de problema.
    • He estado tratando de reproducir la cuestión en la demo de la aplicación pero no hubo suerte todavía. Probablemente el problema realmente en mi código o la 3ª parte de la biblioteca que yo uso. Sigue trabajando en ello. Os mantendré informados si hay un problema con su LayoutManager. Gracias por responder de todos modos.
    • hey @droidev puede usted por favor ayuda m eout con este stackoverflow.com/questions/49952965/…
    • Esta es la respuesta correcta a pesar de la aceptación de uno
    • no funcionó para mí con la horizontal RecyclerView
    • Comprobará que. Yo dint intentar horizontal reciclador de vista
    • Esto funcionó para mí
    • ¿Recuerda a cambio VERTICAL a HORIZONTAL?
    • gracias por este consejo, he resuelto de una manera diferente, pero será el doble check de nuevo

  3. 8

    Podemos tratar como este

        recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView,new RecyclerView.State(), recyclerView.getAdapter().getItemCount());
  4. 7

    Esta es una extensión de las funciones escribí en Kotlin llame directamente en RecyclerView (basado en @Pablo Woitaschek respuesta):

    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)
    }

    Usarlo como este:

    myRecyclerView.smoothSnapToPosition(itemPosition)
  5. 3

    La forma más sencilla que he encontrado para desplazarse de un RecyclerView es como sigue:

    //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);
    • Esto no desplazarse a una posición si esa posición es ya visible. Se desplaza la menos cantidad que se necesita para hacer que la posición visible. Así, ¿por qué necesitamos el uno con el desplazamiento especificado.
  6. 2

    Reemplazar el calculateDyToMakeVisible/calculateDxToMakeVisible función en LinearSmoothScroller para implementar el desplazamiento Y/X posición

    override fun calculateDyToMakeVisible(view: View, snapPreference: Int): Int {
        return super.calculateDyToMakeVisible(view, snapPreference) - ConvertUtils.dp2px(10f)
    }
    • Esto es lo que yo estaba buscando. Gracias por compartir esto para la aplicación de la compensación de la posición de x/y 🙂
  7. 1

    he Utilizado Como Este :

    recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, new RecyclerView.State(), 5);
  8. 0

    Probablemente @droidev enfoque es el correcto, pero quiero publicar algo un poco diferente, lo que hace básicamente el mismo trabajo y no requiere la extensión de la LayoutManager.

    Una NOTA aquí – esto va a funcionar bien si su elemento (la que desea desplazarse en la parte superior de la lista) es visible en la pantalla y lo que desea para desplazarse a la parte superior de forma automática. Es útil cuando el último elemento de la lista tiene un poco de acción, que añade nuevos elementos en la misma lista y desea centrar el 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 para llegar a la cima de coordenadas de la recyclerview elemento;
    2. Necesitamos para llegar a la cima de coordenadas de la vista de elemento que queremos para desplazarse a la parte superior;
    3. Al final con el calculado offset tenemos que hacer

    recyclerView.scrollBy(0, offset);

    200 es sólo ejemplo codificado valor entero que puede utilizar si el viewholder elemento no existe, debido a que también es posible.

Dejar respuesta

Please enter your comment!
Please enter your name here