2015-01-08 3 views
64

В настоящее время я использую следующий код, чтобы проверить, разрешено ли SwipeRefreshLayout.Как узнать, прокручивается ли RecyclerView/LinearLayoutManager сверху или снизу?

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

Но вот в чем проблема. Когда она прокручивается границы зрения другого элемента в mRecyclerView.getChildAt(0).getTop() также возвращает 0.

The problem

Есть ли что-то вроде RecyclerView.isScrolledToBottom() или RecyclerView.isScrolledToTop()?

EDIT: (mRecyclerView.getChildAt(0).getTop() == 0 && linearLayoutManager.findFirstVisibleItemPosition() == 0) вид RecyclerView.isScrolledToTop(), но как насчет RecyclerView.isScrolledToBottom()?

+0

Я полагаю, что последний может быть достигнуто путем проверки в нижней части recyclerview против последнего ребенка то есть что-то на линиях mRecyclerView.getBottom() == linearLayoutmanager.findViewbyPosition (adapter.getItemCount() - 1) .getBottom() – humblerookie

+0

@Saren Arterius вы можете взглянуть на [это] (http://stackoverflow.com/a/33515549/1118886) –

ответ

5

Просто сохранить ссылку на ваш LayoutManager и установить onScrollListener на ваш взгляд ресайклера как этот

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' устарел сейчас. –

+2

Вы должны использовать 'addOnScrollListener', потому что как @shajeelAfzal сказал, что' setOnScrollListener' устарел сейчас, вы должны использовать 'addOnScrollListener', потому что как @shajeelAfzal сказал, что' setOnScrollListener' устарел сейчас, проверьте [здесь] (https://developer.android. com/reference/android/support/v7/widget/RecyclerView.html # setOnScrollListener% 28android.support.v7.widget.RecyclerView.OnScrollListener% 29]) – Vasilisfoo

80

Решение находится в менеджере компоновки.

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 В случае, если ваш размер элемента больше, чем экран использовать следующие для определения вершины событий.

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

PS: На самом деле, если вы поместите RecyclerView непосредственно внутри SwipeRefreshview вам не нужно будет делать это

+0

Нет, это все еще происходит, когда RecyclerView является прямым потомком SwipeRefreshLayout. Но проверка firstCompletelyVisibleItemPosition устраняет проблему. Мне нужно указать что-то здесь. Если ни один из элементов полностью не виден, firstCompletelyVisibleItemPosition() возвращает -1. Поэтому это решение не будет работать, если первый элемент не будет вписываться в RecyclerView при прокрутке вверх. Но это очень редкая ситуация. – eluleci

+0

@eluleci: Проверить, включен ли список RecyclerView rc = (RecyclerView); LinearLayoutManager lm = (LinearLayoutManager) rc.getLayoutManager(); if (lm.findViewByPosition (lm.findFirstVisibleItemPosition()). GetTop() == 0 && lm.findFirstVisibleItemPosition() == 0) return true; // Это будет работать evn, если элемент имеет больший размер, чем экран – humblerookie

+0

Отлично! Мои ряды достаточно короткие, но я думаю, что это будет полезно для других. Спасибо – eluleci

47

Вы можете попробовать recyclerView.canScrollVertically(int direction), если вам просто нужно знать, возможно ли это для прокрутки или не

+0

Это нужно было бы повторять с интервалом, верно? – Stardust

+1

Вы можете это сделать в recyclerView.addOnScrollListener..и работает как шарм ... спасибо – therealprashant

+2

Отлично! Это возвращает false, когда мы доходим до конца прокрутки, мне нужно это событие. – box

27

Чтобы проверить, прокручивается ли снизу RecyclerView. Используйте следующий код.

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

Некоторые Дополнительная информация

Если вы хотите реализовать ScrollToBottom в RecyclerView когда Edittext является tapped то я рекомендую вам добавить 1 секундную задержку так:

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

Работал для меня. Я должен был добавить его в RecyclerView ** addOnScrollListener() **, хотя – aphoe

+1

это не работает для тривиального случая, когда есть один элемент в recyclerview, и он полностью виден. – techtinkerer

+0

вы сохранили день – Reena

17

@Saren Артериус, используя addOnScrollListener из RecycleView, вы можете найти прокрутки в верхней или нижней части вертикального RecycleView, как показано ниже,

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

, но не работают элементы whitout –

+1

Помогли .. скрыть и показать вид –

0

вы можете попробовать с 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; 
} 
0

Я написал RecyclerViewHelper знать recyclerview находится сверху или снизу.

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

вы можете сделать это, это работа для меня

 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

Вы можете обнаружить вершину с помощью следующей

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

Это определит верх, когда вы отпустите палец однажды достиг вершины, , если вы хотите обнаружить, как только reacyclerview достигнет верхней проверки if(IsRecyclerViewAtTop()) внутри onScrolled метод

+0

Спасибо, это работает на нижнем api <16, а также – ir2pid

+1

Это кажется неправильным. 'getChildAt()' возвращает первый дочерний элемент 'ViewGroup', который может (и будет) отличаться от первого элемента списка. Если этот ребенок будет идеально совмещен с верхней частью recyclerview, ваш метод IsRecyclerViewAtTop() будет возвращать true, даже если он не находится наверху. – aspyct