Actualmente estoy usando la de seguir el código para comprobar si SwipeRefreshLayout debe estar habilitado.

private void laySwipeToggle() {
    if (mRecyclerView.getChildCount() == 0 || mRecyclerView.getChildAt(0).getTop() == 0) {
        mLaySwipe.setEnabled(true);
    } else {
        mLaySwipe.setEnabled(false);
    }
}

Pero aquí está el problema. Cuando se desplaza a otro elemento de la vista del límite mRecyclerView.getChildAt(0).getTop() también devuelve 0.

Cómo saber si un RecyclerView /LinearLayoutManager se desplaza a la parte superior o inferior?

Hay algo como RecyclerView.isScrolledToBottom() o RecyclerView.isScrolledToTop()?

EDICIÓN: (mRecyclerView.getChildAt(0).getTop() == 0 && linearLayoutManager.findFirstVisibleItemPosition() == 0) tipo de ¿el RecyclerView.isScrolledToTop(), pero, ¿qué acerca de RecyclerView.isScrolledToBottom()?

  • Supongo que el último puede lograrse mediante la verificación de la parte inferior de la recyclerview contra el último niño que yo.e algo en las líneas de mRecyclerView.getBottom()== linearLayoutmanager.findViewbyPosition(adaptador.getItemCount() – 1).getBottom()
  • Arterius es posible que desee echar un vistazo a este

11 Comentarios

  1. 100

    La solución está en el gestor de diseño.

    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    
    //Add this to your Recycler view
    recyclerView.setLayoutManager(layoutManager);
    
    //To check if at the top of recycler view
    if(layoutManager.firstCompletelyVisibleItemPosition()==0){
        //Its at top
    }
    
    //To check if at the bottom of recycler view
    if(layoutManager.lastCompletelyVisibleItemPosition()==data.size()-1){
        //Its at bottom
    }

    EDITAR

    En caso de que el tamaño del elemento es mayor que el de la pantalla utilice el siguiente para detectar el evento de la parte superior.

    RecyclerView recyclerView = (RecyclerView) view;
    LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
    
    int pos = linearLayoutManager.findFirstVisibleItemPosition();
    
    if(linearLayoutManager.findViewByPosition(pos).getTop()==0 && pos==0){
        return true;
    }

    PS: en Realidad, si el RecyclerView directamente dentro de la SwipeRefreshview usted no necesita hacer esto

    • No, todavía ocurre cuando el RecyclerView es el hijo de SwipeRefreshLayout. Pero la comprobación de la firstCompletelyVisibleItemPosition soluciona el problema. Tengo que señalar algo aquí. Si ninguno de los artículos son totalmente visibles firstCompletelyVisibleItemPosition() devuelve -1. Por lo que esta solución no funcionará si el primer elemento no encaja en el RecyclerView cuando se desplaza a la parte superior. Pero es que es muy rara la situación.
    • Compruebe si la lista está en la parte superior RecyclerView rc=(RecyclerView)vista; LinearLayoutManager lm= (LinearLayoutManager) rc.getLayoutManager(); if(lm.findViewByPosition(lm.findFirstVisibleItemPosition()).getTop()==0 && lm.findFirstVisibleItemPosition()==0) return true; //Esto funciona evn si el elemento es de un tamaño más grande que la pantalla
    • Genial!!! Mi filas son lo suficientemente corto pero creo que te va a ser útil a los demás. Gracias
    • Esto produciría un error si el elemento (la primera o la última) es mayor que la totalidad de la pantalla. Porque, first/lastCompletelyVisibleItemPosition() devolverá -1, implica, no es totalmente elemento visible a todos.
    • Así me gustaría que la gente tome tiempo para leer la respuesta completa. Th edición on Jun 1, menciona el caso muy
    • Sólo lastVisibleItemPosition trabajado conmigo sin Completely
    • Ambos lastVisibleItemPosition y lastCompletelyVisibleItemPosition no funcionan. (no se puede resolver el método). Ayuda?
    • Hola, he resuelto mi problema de uso de la final android.support.v7.widget.LinearLayoutManager layoutManager = new LinearLayoutManager(this); (ver stackoverflow.com/questions/29327013/…)
    • También, el uso de findLastCompletelyVisibleItemPosition.
    • Gracias!!! me ayudó mucho
    • findLastCompletelyVisibleItemPosition FALLARÁ si el último elemento de la altura es mayor que la altura de la pantalla. Esto significa que el último elemento es visible, pero no completamente visible, por lo que layout.findLastCompletelyVisibleItemPosition()=-1(RecyclerView.NO_POSITION). Uso lastVisibleItemPosition y de verificación de la parte inferior de la última vista en el diseño será más seguro.
    • greate! muchas gracias
    • recyclerView.getLayoutManager() no tiene esos métodos, porque devuelve un LayoutManager y no un LinearLayoutManager(que tiene el método que desea)
    • Lo que me estoy perdiendo aquí, ¿no es lo que se explica en la solución a través de código?
    • me estaba explicando a @Stardust ¿por qué no existe ningún método

  2. 59

    Puede intentar recyclerView.canScrollVertically(int direction), si usted sólo necesita saber si es posible el desplazamiento o no.

    Dirección enteros:

    • -1 hasta
    • 1 para abajo
    • 0 siempre devolverá false.
    • Este tendría que ser repetido en un intervalo, aunque, a la derecha?
    • Puede esta en recyclerView.addOnScrollListener..funciona como un encanto…gracias
    • Genial!!! Este devuelve un false cuando llegamos al final de desplazamiento, necesitaba este evento.
    • Excelente. El uso de este en onScrollStateChanged funciona para mí.
    • sólo recuerde: en caso de que ningún elemento para mostrar o elemento no es suficiente para desplazarse, siempre devolverá false
    • recyclerView.canScrollVertically(RecyclerView.FOCUS_DOWN) == false has llegado a la parte inferior
    • dirección enteros: -1 para arriba, 1 abajo, 0 siempre devolverá false.

  3. 32

    Con el fin de comprobar si RecyclerView se desplaza a la parte inferior. Utilice el siguiente código.

    /**
         * Check whether the last item in RecyclerView is being displayed or not
         *
         * @param recyclerView which you would like to check
         * @return true if last position was Visible and false Otherwise
         */
        private boolean isLastItemDisplaying(RecyclerView recyclerView) {
            if (recyclerView.getAdapter().getItemCount() != 0) {
                int lastVisibleItemPosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findLastCompletelyVisibleItemPosition();
                if (lastVisibleItemPosition != RecyclerView.NO_POSITION && lastVisibleItemPosition == recyclerView.getAdapter().getItemCount() - 1)
                    return true;
            }
            return false;
        }

    Algo de información Adicional

    Si quieres implementar ScrollToBottom en RecyclerView cuando Edittext es tapped entonces te recomiendo agregar 1 segundo de retraso como este:

     edittext.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_UP)
                        if (isLastItemDisplaying(recyclerView)) {
    //The scrolling can happen instantly before keyboard even opens up so to handle that we add 1 second delay to scrolling
                            recyclerView.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    recyclerView.smoothScrollToPosition(recyclerView.getAdapter().getItemCount() - 1);
    
                                }
                            }, 1000);
                        }
                    return false;
                }
            });
    • Trabajó para mí. He tenido que añadir a la RecyclerView del addOnScrollListener() a pesar de que
    • esto no funciona para el caso trivial donde hay un elemento en el recyclerview y es totalmente visible.
    • guardó un día
  4. 20

    @Saren Arterius, el Uso de la addOnScrollListener de RecycleView, usted puede encontrar el desplazamiento de la parte superior o inferior de la Vertical RecycleView como el de abajo,

    RecyclerView rv = (RecyclerView)findViewById(R.id.rv);
    
    rv.addOnScrollListener(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) {
    
                    if (dy < 0) {
                        //Recycle view scrolling up...
    
                    } else if (dy > 0) {
                        //Recycle view scrolling down...
                    }
                }
            });
    • pero no funcionan whitout elementos
    • Ayudado..para ocultar y mostrar la vista
  5. 5

    Mantener una referencia a su layoutManager y establecer onScrollListener en su reciclador de vista de esta

    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
    
            visibleItemCount = mRecyclerView.getChildCount();
            totalItemCount = mLayoutManager.getItemCount();
            firstVisibleItemIndex = mLayoutManager.findFirstVisibleItemPosition();
    
            //synchronizew loading state when item count changes
            if (loading) {
                if (totalItemCount > previousTotal) {
                    loading = false;
                    previousTotal = totalItemCount;
                }
            }
            if (!loading)
                if ((totalItemCount - visibleItemCount) <= firstVisibleItemIndex) {
                    //Loading NOT in progress and end of list has been reached
                    //also triggered if not enough items to fill the screen
                    //if you start loading
                    loading = true;
                } else if (firstVisibleItemIndex == 0){
                    //top of list reached
                    //if you start loading
                    loading = true;
                }
            }
        }
    });
    • setOnScrollListner es obsoleto ahora.
    • Usted debe utilizar addOnScrollListener porque como @shajeelAfzal dijo setOnScrollListener es obsoleto ahora , usted debe utilizar addOnScrollListener porque como @shajeelAfzal dijo setOnScrollListener es obsoleto ahora , consulte aquí
    • ¿Qué es previousTotal?
  6. 5

    Uso recyclerView.canScrollVertically(int orientación) para comprobar si la parte superior o inferior de las barras de desplazamiento alcanzado.

    dirección = 1 para desplazarse hacia abajo (inferior)

    dirección = -1 para desplazarse hacia arriba (top)

    si el método devuelve false eso significa que usted llegó, ya sea superior o inferior depende de la dirección.

  7. 3

    Puede detectar la parte superior mediante la siguiente

     recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
              }
    
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if(IsRecyclerViewAtTop())
                {
                    //your recycler view reached Top do some thing
                 }
            }
        });
    
      private boolean IsRecyclerViewAtTop()   {
            if(recyclerView.getChildCount() == 0)
                return true;
            return recyclerView.getChildAt(0).getTop() == 0;
        }

    Esto permitirá detectar superior cuando suelte el dedo una vez llegado a la cima,
    si desea detectar tan pronto como el reacyclerview llega a la parte superior de verificación if(IsRecyclerViewAtTop()) dentro de onScrolled método

    • Gracias, esto funciona en la parte inferior de la api < 16 así
    • Este parece ser el mal. getChildAt() devuelve el primer hijo de la ViewGroup, que pueden (y será) diferente de la que el primer elemento de la lista. Si el niño pasa a estar perfectamente alineado con la parte superior de la recyclerview, su IsRecyclerViewAtTop() método devolverá true, aunque no es en la parte superior.
  8. 2

    He escrito un RecyclerViewHelper saber el recyclerview es en la parte superior o en la parte inferior.

    public class RecyclerViewHelper {
    public static boolean isAtTop(RecyclerView recyclerView) {
    if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    return isAtTopBeforeIceCream(recyclerView);
    } else {
    return !ViewCompat.canScrollVertically(recyclerView, -1);
    }
    }
    private static boolean isAtTopBeforeIceCream(RecyclerView recyclerView) {
    RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
    if (layoutManager instanceof LinearLayoutManager) {
    LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
    int pos = linearLayoutManager.findFirstVisibleItemPosition();
    if (linearLayoutManager.findViewByPosition(pos).getTop() == recyclerView.getPaddingTop() && pos == 0)
    return true;
    }
    return false;
    }
    public static boolean isAtBottom(RecyclerView recyclerView) {
    if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    return isAtBottomBeforeIceCream(recyclerView);
    } else {
    return !ViewCompat.canScrollVertically(recyclerView, 1);
    }
    }
    private static boolean isAtBottomBeforeIceCream(RecyclerView recyclerView) {
    RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
    int count = recyclerView.getAdapter().getItemCount();
    if (layoutManager instanceof LinearLayoutManager) {
    LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
    int pos = linearLayoutManager.findLastVisibleItemPosition();
    int lastChildBottom = linearLayoutManager.findViewByPosition(pos).getBottom();
    if (lastChildBottom == recyclerView.getHeight() - recyclerView.getPaddingBottom() && pos == count - 1)
    return true;
    }
    return false;
    }

    }

  9. 2

    usted puede hacer esto es un trabajo para mí

          mRecycleView.addOnScrollListener(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);
    int topRowVerticalPosition = (recyclerView == null || recyclerView.getChildCount() == 0) ?
    0 : recyclerView.getChildAt(0).getTop();
    LinearLayoutManager linearLayoutManager1 = (LinearLayoutManager) recyclerView.getLayoutManager();
    int firstVisibleItem = linearLayoutManager1.findFirstVisibleItemPosition();
    swipeRefreshLayout.setEnabled(firstVisibleItem == 0 && topRowVerticalPosition >= 0);
    }
    });
  10. 1

    puedes probar con el OnTouchListener:

    recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
    if (e.getAction() == MotionEvent.ACTION_UP
    || e.getAction() == MotionEvent.ACTION_MOVE){
    if (mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() > 0)
    {
    //beginning of the recycler 
    }
    if (mLinearLayoutManager.findLastCompletelyVisibleItemPosition()+1 < recyclerView.getAdapter().getItemCount())
    {
    //end of the recycler 
    }         
    }             
    return false;
    }
  11. 0

    Para averiguar si el RecyclerView se desplaza a la parte inferior, usted podría reutilizar los métodos utilizados para la barra de desplazamiento.

    Este es el cálculo, para una mayor comodidad escrito como un Kotlin función de extensión:

    fun RecyclerView.isScrolledToBottom(): Boolean {
    val contentHeight = height - (paddingTop + paddingBottom)
    return computeVerticalScrollRange() == computeVerticalScrollOffset() + contentHeight
    }
    • Solución agradable! He visto algunas cuestiones en las que el tamaño del scroll era de sólo el 1, aunque yo se desplaza en la parte inferior (probablemente algunos problemas de redondeo) Así que he cambiado el código para utilizar un margen de: fun RecyclerView.isScrolledToBottom(margin: Int = 1): Boolean { val contentHeight = height - (paddingTop + paddingBottom) return computeVerticalScrollRange() - computeVerticalScrollOffset() - contentHeight >= margin }
    • Quiero decir, menor o igual al margen. Como este: fun RecyclerView.isScrolledToBottom(margin: Int = 1): Boolean { val contentHeight = height - (paddingTop + paddingBottom) return computeVerticalScrollRange() - computeVerticalScrollOffset() - contentHeight <= margin }

Dejar respuesta

Please enter your comment!
Please enter your name here