2015-01-08 6 views
64

Derzeit verwende ich den folgenden Code, um zu überprüfen, ob SwipeRefreshLayout aktiviert werden sollte.Wie kann man feststellen, ob ein RecyclerView/LinearLayoutManager nach oben oder unten gescrollt wird?

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

Aber hier ist das Problem. Wenn es um ein anderes Element der Ansicht der Grenze gescrollt ist mRecyclerView.getChildAt(0).getTop() kehrt auch 0.

The problem

Gibt es so etwas wie RecyclerView.isScrolledToBottom() oder RecyclerView.isScrolledToTop()?

EDIT: (mRecyclerView.getChildAt(0).getTop() == 0 && linearLayoutManager.findFirstVisibleItemPosition() == 0) Art von tut die RecyclerView.isScrolledToTop(), aber was ist mit RecyclerView.isScrolledToBottom()?

+0

Ich nehme diese kann durch die Überprüfung der Unterseite des recyclerview gegen das letzte Kind also etwas auf den Linien von mRecyclerView.getBottom() == linearLayoutmanager.findViewbyPosition (adapter.getItemCount() erreicht werden - 1) .getBottom() – humblerookie

+0

@Saren Arterius möchten Sie vielleicht einen Blick auf [this] werfen (http://stackoverflow.com/a/33515549/1118886) –

Antwort

5

Halten Sie einfach einen Verweis auf Ihre Layoutmanager und setzte onScrollListener auf Recycler Ansicht wie diese

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; 
      } 
     } 
    } 
}); 
+1

'setOnScrollListner' ist jetzt veraltet. –

+2

Sie sollten 'addOnScrollListener' verwenden, da @shajeelAfzal sagte' setOnScrollListener' ist jetzt veraltet, sollten Sie 'addOnScrollListener' verwenden, da @shajeelAfzal sagte 'setOnScrollListener' ist jetzt veraltet, kreuzen Sie [hier] an (https://developer.android. com/reference/android/support/v7/widget/RecyclerView.html # setOnScrollListener% 28android.support.v7.widget.RecyclerView.OnScrollListener% 29]) – Vasilisfoo

80

Die Lösung in dem Layout-Manager ist.

LinearLayoutManager layoutManager=new LinearLayoutManager(this); 
//Add this to your Recyclerview 
recyclerview.setLayoutManager(layoutManager); 

//Tocheck if recycler is on top 
if(layoutManager.firstCompletelyVisibleItemPosition()==0){ 
//Its at top .. 
} 

//Tocheck if recycler is on bottom 
    if(layoutManager.lastCompletelyVisibleItemPosition()==data.size()-1){ 
    //Its at bottom .. 
    } 

EDIT Falls Ihre Elementgröße größer als der Bildschirm des folgend verwenden, um das Top-Ereignis zu erfassen.

RecyclerView rc=(RecyclerView)view; 
LinearLayoutManager lm= (LinearLayoutManager) rc.getLayoutManager(); 
int pos = lm.findFirstVisibleItemPosition(); 
if(lm.findViewByPosition(pos).getTop()==0 && pos==0) 
return true; 

PS: Eigentlich, wenn Sie die RecyclerView direkt im SwipeRefreshview platzieren müssen Sie nicht diese

+0

Nein, es passiert immer noch, wenn das RecyclerView das direkte Kind von SwipeRefreshLayout ist. Das Überprüfen der ersten CompletelyVisibleItemPosition behebt das Problem. Ich muss hier etwas zeigen. Wenn keines der Elemente vollständig sichtbar ist, gibt firstCompletelyVisibleItemPosition() -1 zurück. Daher funktioniert diese Lösung nicht, wenn das erste Element nicht in den RecyclerView passt, wenn es nach oben gescrollt wird. Aber es ist eine sehr seltene Situation. – eluleci

+0

@eluleci: Prüfen, ob die Liste oben steht RecyclerView rc = (RecyclerView) Ansicht; LinearLayoutManager lm = (LinearLayoutManager) rc.getLayoutManager(); if (lm.findViewByPosition (lm.findFirstVisibleItemPosition()). GetTop() == 0 && lm.findFirstVisibleItemPosition() == 0) return true; // Dies würde evn funktionieren, wenn der Artikel größer als der Bildschirm ist – humblerookie

+0

Großartig! Meine Reihen sind kurz genug, aber ich denke, dass es für andere hilfreich sein wird. Danke – eluleci

47

tun können Sie recyclerView.canScrollVertically(int direction) versuchen, wenn Sie müssen nur wissen, ob es möglich, zu blättern oder nicht

+0

Das müsste in einem Intervall wiederholt werden, oder? – Stardust

+1

Sie können dies in RecyclerView.addOnScrollListener..es funktioniert wie ein Charme ... danke – therealprashant

+2

Großartig! Dies führt zu einem falschen Ergebnis, wenn wir das Ende des Scrollens erreicht haben. Ich brauchte dieses Ereignis. – box

27

Um zu überprüfen, ob RecyclerView nach unten gescrollt wird. Verwenden Sie den folgenden Code.

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

Einige Zusatzinfo

Wenn Sie ScrollToBottom in RecyclerView implementieren möchten, wenn Edittexttapped ist dann Sie 1 Sekunde Verzögerung wie dies empfehle ich hinzufügen:

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; 
      } 
     }); 
+0

Arbeitete für mich. Ich musste es zu den RecyclerView ** AddOnScrollListener() hinzufügen ** obwohl – aphoe

+1

dies nicht funktioniert für den trivialen Fall, wo es ein Element in der Recyclerview ist und es vollständig sichtbar ist. – techtinkerer

+0

Sie speicherten einen Tag – Reena

17

@Saren Arterius, mit dem addOnScrollListener von RecycleView, können Sie das Scrollen oben oder unten vertikal RecycleView wie unten finden,

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... 
       } 
      } 
     }); 
+0

aber funktionieren nicht ohne Elemente –

+1

Geholfen..zu verstecken und Show –

0

Sie können mit dem OnTouchListener versuchen:

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

ich geschrieben habe eine RecyclerViewHelper die recyclerview wissen ist oben oder unten.

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

}

2

können Sie diese es Arbeit für mich tun

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

Sie können oben erkennen, indem Sie den folgenden

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

verwendet, wird dieser oben erkennen, wenn Sie die Freigabe Finger einmal oben erreicht, wenn Sie erkennen möchten, sobald der ReacyclerView Top Check 01 erreichtinnerhalb onScrolled Methode

+0

Danke, das funktioniert auf niedrigeren api <16 sowie – ir2pid

+1

Dies scheint falsch zu sein. 'getChildAt()' gibt das erste Kind der 'ViewGroup' zurück, das sich vom ersten Element der Liste unterscheiden kann (und wird). Wenn dieses Kind perfekt mit dem Anfang der Recycler-Ansicht ausgerichtet ist, gibt Ihre 'IsRecyclerViewAtTop()' -Methode "true" zurück, obwohl sie nicht ganz oben steht. – aspyct

Verwandte Themen