Necesito para detectar el inicio/final y la dirección de desplazamiento en una recyclerview. El desplazamiento en la escucha de dos métodos: onScrolled() y onScrollStateChanged(). El primer método es llamado después de que el desplazamiento se inicia (de hecho se llama onScrolled() y no onScrolling()). El segundo método proporciona información sobre el estado pero no tengo la información de la dirección. ¿Cómo puedo lograr mi objetivo?

InformationsquelleAutor greywolf82 | 2015-10-31

6 Comentarios

  1. 77

    el paso 1 Se puede crear una clase que extiende RecyclerView.OnScrollListener y reemplazar estos métodos

    public class CustomScrollListener extends RecyclerView.OnScrollListener {
        public CustomScrollListener() {
        }
    
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            switch (newState) {
                case RecyclerView.SCROLL_STATE_IDLE:
                    System.out.println("The RecyclerView is not scrolling");
                    break;
                case RecyclerView.SCROLL_STATE_DRAGGING:
                    System.out.println("Scrolling now");
                    break;
                case RecyclerView.SCROLL_STATE_SETTLING:
                    System.out.println("Scroll Settling");
                    break;
    
            }
    
        }
    
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            if (dx > 0) {
                System.out.println("Scrolled Right");
            } else if (dx < 0) {
                System.out.println("Scrolled Left");
            } else {
                System.out.println("No Horizontal Scrolled");
            }
    
            if (dy > 0) {
                System.out.println("Scrolled Downwards");
            } else if (dy < 0) {
                System.out.println("Scrolled Upwards");
            } else {
                System.out.println("No Vertical Scrolled");
            }
        }
    }

    paso 2 – Desde setOnScrollListener está en desuso es mejor utilizar addOnScrollListener

     mRecyclerView.addOnScrollListener(new CustomScrollListener());
    • RecyclerView.OnScrollListener no es una interfaz /facepalm @ google dev, quien decidió que.
  2. 37

    Consulte la documentación de onScrollStateChanged(int estado).
    Los tres valores posibles son:

    • SCROLL_STATE_IDLE: No hay desplazamiento se realiza.
    • SCROLL_STATE_DRAGGING: El usuario está arrastrando su dedo sobre la pantalla (o se lo hace a través de programación.
    • SCROLL_STATE_SETTLING: Usuario ha levantado su dedo, y la animación se ha ralentizado.

    Así que si usted desea detectar cuando el desplazamiento inicial y final, entonces usted puede crear algo como esto:

    public void onScrollStateChanged(int state) {
        boolean hasStarted = state == SCROLL_STATE_DRAGGING;
        boolean hasEnded = state == SCROLL_STATE_IDLE;
    }
    • OK, pero ¿cómo se puede detectar incluso la dirección en el mismo tiempo?
    • Puede reemplazar onScrolled(int dx, int dy) y comprobar si dy es positivo o negativo, que le da una o la otra dirección.
  3. 3

    Manera más fácil de hacer es sacar tu layoutManager. Por ejemplo

       private RecyclerView.OnScrollListener mListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
    
            GridLayoutManager layoutManager=GridLayoutManager.class.cast(recyclerView.getLayoutManager());
            int visibleItemCount = layoutManager.getChildCount();
            int totalItemCount = layoutManager.getItemCount();
            int pastVisibleItems = layoutManager.findFirstCompletelyVisibleItemPosition();
    
            if(pastVisibleItems+visibleItemCount >= totalItemCount){
                //End of the list is here.
                Log.i(TAG, "End of list");
            }
        }
    }

    Espero que ayude!

  4. 2

    Utilizar este código para evitar llamadas repetidas

    utilice -1 para la detección de la parte superior

            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
    
                if (!recyclerView.canScrollVertically(1) && newState==RecyclerView.SCROLL_STATE_IDLE) {
                    Log.d("-----","end");
    
                }
            }
        });
  5. 0

    aquí está la solución completa para realizar una acción después de desplazamiento se detiene (por RecyclerView)

    que ha corregido mi Excepción OutOfBounds relacionados con la recyclerView desplazamiento

    recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
                        @Override
                        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                            //Your action here
                        }
                    });
  6. 0

    Creo que las otras respuestas no toque su punto de dolor.

    Acerca de la cuestión

    Como usted dijo, RecycleView invocará onScrollStateChanged() antes de onScrolled() método. Sin embargo, onScrollStateChanged() método sólo puede decir la RecycleView tres de estado:

    • SCROLL_STATE_IDLE
    • SCROLL_STATE_DRAGGING
    • SCROLL_STATE_SETTLING

    Que significa, asumir la RecycleView es en su parte superior ahora, si el usuario se desplaza hacia arriba, sólo puede desencadenar onScrollStateChanged() método, pero no onScrolled() método.
    Y si el usuario se desplaza hacia abajo, puede desencadenar onScrollStateChanged() método en primer lugar, a continuación, onScrolled() método.

    Entonces el problema viene, SCROLL_STATE_DRAGGING sólo puedo decirte que arrastra el usuario de la vista, no indicar la dirección de su arrastre.

    Tienes que combinar con el dy de onScrolled() método para detectar el arrastre de dirección, pero onScrolled() no se desencadena con onScrollStateChanged().

    MySolution:

    Registro de desplazamiento de estado cuando se onScrollStateChanged() activa, entonces deley un tiempo, como 10ms, compruebe si tiene un eje de movimiento, y hacer una conclusión de arrastre de dirección.

    Kotlin Código:

    class DraggingDirectionScrollListener(private val view: View)
    : RecyclerView.OnScrollListener() {
    private val DIRECTION_NONE = -1
    private val DIRECTION_UP = 0
    private val DIRECTION_DOWN = 1
    var scrollDirection = DIRECTION_NONE
    var listStatus = RecyclerView.SCROLL_STATE_IDLE
    var totalDy = 0
    override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
    listStatus = newState
    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
    scrollDirection = DIRECTION_NONE
    }
    if (isOnTop() && newState == RecyclerView.SCROLL_STATE_DRAGGING) {
    view.postDelayed({
    if (getDragDirection() == DIRECTION_DOWN){
    //Drag down from top
    }else if (getDragDirection() == DIRECTION_UP) {
    //Drag Up from top
    }
    }, 10)
    }
    }
    override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
    this.totalDy += dy
    scrollDirection = when {
    dy > 0 -> DIRECTION_UP
    dy < 0 -> DIRECTION_DOWN
    else -> DIRECTION_NONE
    }
    }
    /**
    * is on the top of the list
    */
    private fun isOnTop():Boolean{
    return totalDy == 0
    }
    /**
    * detect dragging direction
    */
    private fun getDragDirection():Int {
    if (listStatus != RecyclerView.SCROLL_STATE_DRAGGING) {
    return DIRECTION_NONE
    }
    return when (scrollDirection) {
    DIRECTION_NONE -> if (totalDy == 0){
    DIRECTION_DOWN  //drag down from top
    }else{
    DIRECTION_UP  //drag up from bottom
    }
    DIRECTION_UP -> DIRECTION_UP
    DIRECTION_DOWN -> DIRECTION_DOWN
    else -> DIRECTION_NONE
    }
    }
    }

Dejar respuesta

Please enter your comment!
Please enter your name here