J'utilise actuellement le code suivant pour vérifier si SwipeRefreshLayout doit être activé.
private void laySwipeToggle() {
if (mRecyclerView.getChildCount() == 0 || mRecyclerView.getChildAt(0).getTop() == 0) {
mLaySwipe.setEnabled(true);
} else {
mLaySwipe.setEnabled(false);
}
}
Mais voici le problème. Lorsqu'il défile vers la vue d'un autre élément, la fonction mRecyclerView.getChildAt(0).getTop()
renvoie également 0.
Existe-t-il quelque chose comme RecyclerView.isScrolledToBottom()
ou RecyclerView.isScrolledToTop()
?
EDIT: (mRecyclerView.getChildAt(0).getTop() == 0 && linearLayoutManager.findFirstVisibleItemPosition() == 0)
genre de RecyclerView.isScrolledToTop()
, mais qu'en est-il de RecyclerView.isScrolledToBottom()
?
La solution est dans le gestionnaire de disposition.
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
}
MODIFIER
Si la taille de votre élément est supérieure à celle de l’écran, utilisez ce qui suit pour détecter le premier événement.
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 fait, si vous placez la RecyclerView
directement dans la SwipeRefreshview
, vous n’auriez pas besoin de le faire
Vous pouvez essayer recyclerView.canScrollVertically(int direction)
, si vous avez juste besoin de savoir s'il est possible de faire défiler ou non
Afin de vérifier si RecyclerView
est défilé vers le bas. Utilisez le code suivant.
/**
* 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;
}
Quelques informations supplémentaires
Si vous voulez implémenter ScrollToBottom
dans RecyclerView
lorsque Edittext
est tapped
, je vous recommande d'ajouter délai de 1 seconde comme ceci:
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;
}
});
@Saren Arterius, à l'aide de addOnScrollListener de RecycleView , vous pouvez trouver le haut ou le bas de défilement vertical de RecycleView vertical comme ci-dessous,
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...
}
}
});
Conservez simplement une référence à votre layoutManager et définissez onScrollListener sur votre vue Recycler comme ceci
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;
}
}
}
});
Utilisez recyclerView.canScrollVertically (int direction) pour vérifier si le haut ou le bas du défilement est atteint.
direction = 1 pour défiler vers le bas (bas)
direction = -1 pour défiler vers le haut (haut)
si méthode renvoie false, cela signifie que vous avez atteint le haut ou le bas, cela dépend de la direction.
Vous pouvez détecter le haut en utilisant les méthodes suivantes
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;
}
Ceci détectera top lorsque vous relâchez le doigt une fois atteint top, Si vous souhaitez détecter dès que la vue récapitulative atteint top check if(IsRecyclerViewAtTop())
dans la méthode onScrolled
tu peux le faire c'est travailler pour moi
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);
}
});
J'ai écrit un RecyclerViewHelper pour savoir que le recyclage est en haut ou en bas.
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;
}
}
vous pouvez essayer avec 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;
}
Pour savoir si RecyclerView est défilé jusqu'en bas, vous pouvez réutiliser les méthodes utilisées pour la barre de défilement.
Ceci est le calcul, pour plus de commodité, écrit sous la forme d'une fonction d'extension Kotlin:
fun RecyclerView.isScrolledToBottom(): Boolean {
val contentHeight = height - (paddingTop + paddingBottom)
return computeVerticalScrollRange() == computeVerticalScrollOffset() + contentHeight
}