How to know whether a RecyclerView / LinearLayoutManager is scrolled to top or bottom?

后端 未结 11 2053
一向
一向 2020-12-02 06:24

Currently I am using the follow code to check whether SwipeRefreshLayout should be enabled.

private void laySwipeToggle() {
    if (mRecyclerView.getChildCou         


        
相关标签:
11条回答
  • 2020-12-02 07:03

    Use recyclerView.canScrollVertically(int direction) to check if top or bottom of the scroll reached.

    direction = 1 for scroll down (bottom)

    direction = -1 for scroll up (top)

    if method return false that means you reached either top or bottom depends on the direction.

    0 讨论(0)
  • 2020-12-02 07:03

    you can try with the 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 讨论(0)
  • 2020-12-02 07:05

    The solution is in the layout manager.

    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
    }
    

    EDIT

    In case your item size is larger than the screen use the following to detect the top event.

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

    PS: Actually, if you place the RecyclerView directly inside the SwipeRefreshview you wouldn't need to do this

    0 讨论(0)
  • 2020-12-02 07:05

    I have written a RecyclerViewHelper to know the recyclerview is at top or at bottom.

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

    }

    0 讨论(0)
  • 2020-12-02 07:07

    Just keep a reference to your layoutManager and set onScrollListener on your recycler view like this

    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;
                }
            }
        }
    });
    
    0 讨论(0)
提交回复
热议问题