Actualmente estoy usando el siguiente código para verificar si SwipeRefreshLayout debería 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 al límite de la vista de otro elemento, mRecyclerView.getChildAt(0).getTop()
también devuelve 0.
¿Hay algo como RecyclerView.isScrolledToBottom()
o RecyclerView.isScrolledToTop()
?
EDITAR: (mRecyclerView.getChildAt(0).getTop() == 0 && linearLayoutManager.findFirstVisibleItemPosition() == 0)
algo así como RecyclerView.isScrolledToTop()
, pero ¿de qué RecyclerView.isScrolledToBottom()
?
android
android-recyclerview
Saren Arterius
fuente
fuente
Respuestas:
La solución está en el administrador 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 de su artículo sea más grande que la pantalla, utilice lo siguiente para detectar el evento principal.
RecyclerView recyclerView = (RecyclerView) view; LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); int pos = linearLayoutManager.findFirstVisibleItemPosition(); if(linearLayoutManager.findViewByPosition(pos).getTop()==0 && pos==0){ return true; }
PD: En realidad, si coloca el
RecyclerView
directamente dentro delSwipeRefreshview
, no necesitaría hacer estofuente
first/lastCompletelyVisibleItemPosition()
devolverá -1, implica que no hay ningún elemento completamente visible.lastVisibleItemPosition
ylastCompletelyVisibleItemPosition
no funcionan. (no se puede resolver el método). ¿Ayuda?findLastCompletelyVisibleItemPosition
FALLARÁ si la altura del último elemento es mayor que la altura de la pantalla. Significa que el último elemento es visible, pero no completamente visible, entonceslayout.findLastCompletelyVisibleItemPosition()=-1(RecyclerView.NO_POSITION)
. UsarlastVisibleItemPosition
y verificar la parte inferior de la última vista en el diseño será más seguro.Puede intentarlo
recyclerView.canScrollVertically(int direction)
, si solo necesita saber si es posible desplazarse o no.Enteros de dirección:
fuente
onScrollStateChanged
obras para mí.Para comprobar si
RecyclerView
se desplaza hacia abajo. 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; }
Alguna información adicional
Si se desea implementar
ScrollToBottom
enRecyclerView
cuandoEdittext
estapped
entonces le recomiendo que añadir retardo de 1 segundo de esta manera: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; } });
fuente
@Saren Arterius, utilizando el addOnScrollListener de RecycleView , puede encontrar la parte superior o inferior de desplazamiento vertical RecycleView como se muestra a continuación,
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... } } });
fuente
Use recyclerView.canScrollVertically (dirección int) para verificar si se alcanzó la parte superior o inferior del desplazamiento.
dirección = 1 para desplazarse hacia abajo (abajo)
dirección = -1 para desplazarse hacia arriba (arriba)
si el método devuelve falso, eso significa que alcanzó la parte superior o inferior depende de la dirección.
fuente
Simplemente mantenga una referencia a su layoutManager y configure onScrollListener en su vista de reciclador de esta manera
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; } } } });
fuente
setOnScrollListner
ahora está en desuso.addOnScrollListener
porque como dijo @shajeelAfzalsetOnScrollListener
ahora está en desuso, debe usaraddOnScrollListener
porque como dijo @shajeelAfzalsetOnScrollListener
ahora está en desuso, verifique aquípreviousTotal
?Puede detectar la parte superior utilizando lo 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 detectará la parte superior cuando suelte el dedo una vez que haya alcanzado la parte superior, si desea detectar tan pronto como el reacyclerview alcance la parte superior, compruebe el método
if(IsRecyclerViewAtTop())
internoonScrolled
fuente
getChildAt()
devuelve el primer hijo deViewGroup
, que podría (y será) diferente del primer elemento de la lista. Si ese niño está perfectamente alineado con la parte superior de la vista de reciclaje, suIsRecyclerViewAtTop()
método devolverá verdadero, aunque no esté en la parte superior.He escrito un RecyclerViewHelper para saber que la vista de reciclaje está arriba o abajo.
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; }
}
fuente
puedes 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); } });
fuente
Para saber si el RecyclerView se desplaza hacia abajo, puede reutilizar los métodos utilizados para la barra de desplazamiento.
Este es el cálculo, escrito por conveniencia como una función de extensión de Kotlin:
fun RecyclerView.isScrolledToBottom(): Boolean { val contentHeight = height - (paddingTop + paddingBottom) return computeVerticalScrollRange() == computeVerticalScrollOffset() + contentHeight }
fuente
fun RecyclerView.isScrolledToBottom(margin: Int = 1): Boolean { val contentHeight = height - (paddingTop + paddingBottom) return computeVerticalScrollRange() - computeVerticalScrollOffset() - contentHeight >= margin }
fun RecyclerView.isScrolledToBottom(margin: Int = 1): Boolean { val contentHeight = height - (paddingTop + paddingBottom) return computeVerticalScrollRange() - computeVerticalScrollOffset() - contentHeight <= margin }
puedes probar con 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; }
fuente