简体   繁体   English

如何知道 RecyclerView / LinearLayoutManager 是滚动到顶部还是底部?

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

Currently I am using the follow code to check whether SwipeRefreshLayout should be enabled.目前我正在使用以下代码来检查是否应启用 SwipeRefreshLayout。

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

But here is the problem.但问题就在这里。 When it's scrolled to another item's view's boundary mRecyclerView.getChildAt(0).getTop() also returns 0.当它滚动到另一个项目的视图边界时, mRecyclerView.getChildAt(0).getTop()也返回 0。

问题

Is there something like RecyclerView.isScrolledToBottom() or RecyclerView.isScrolledToTop() ?有没有像RecyclerView.isScrolledToBottom()RecyclerView.isScrolledToTop()

EDIT: (mRecyclerView.getChildAt(0).getTop() == 0 && linearLayoutManager.findFirstVisibleItemPosition() == 0) kind of does the RecyclerView.isScrolledToTop() , but what about RecyclerView.isScrolledToBottom() ?编辑: (mRecyclerView.getChildAt(0).getTop() == 0 && linearLayoutManager.findFirstVisibleItemPosition() == 0)有点RecyclerView.isScrolledToTop() ,但是RecyclerView.isScrolledToBottom()呢?

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 PS:实际上,如果您将RecyclerView直接放在SwipeRefreshview ,则不需要这样做

You can try recyclerView.canScrollVertically(int direction) , if you just need to know whether it possible to scroll or not.您可以尝试recyclerView.canScrollVertically(int direction) ,如果您只需要知道是否可以滚动。

Direction integers:方向整数:

  • -1 for up -1 向上
  • 1 for down 1 羽绒
  • 0 will always return false. 0 将始终返回 false。

In order to check whether RecyclerView is scrolled to bottom.为了检查RecyclerView是否滚动到底部。 Use the following 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;
    }

Some Additional info一些附加信息

If you want to implement ScrollToBottom in RecyclerView when Edittext is tapped then i recommend you add 1 second delay like this:如果您想在tapped Edittext时在RecyclerView实现ScrollToBottom ,那么我建议您添加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;
            }
        });

@Saren Arterius, Using the addOnScrollListener of RecycleView , you can find the scrolling top or bottom of Vertical RecycleView like below, @Saren Arterius,使用RecycleViewaddOnScrollListener ,您可以找到垂直 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...
                }
            }
        });

Use recyclerView.canScrollVertically(int direction) to check if top or bottom of the scroll reached.使用recyclerView.canScrollVertically(int direction)检查是否到达滚动的顶部或底部。

direction = 1 for scroll down (bottom)方向 = 1 向下滚动(底部)

direction = -1 for scroll up (top)方向 = -1 向上滚动(顶部)

if method return false that means you reached either top or bottom depends on the direction. if 方法返回 false 意味着您到达顶部或底部取决于方向。

Just keep a reference to your layoutManager and set onScrollListener on your recycler view like this只需保留对您的 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;
            }
        }
    }
});

You can detect top by using the following您可以使用以下方法检测顶部

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

This will detect top when you release the finger once reached top, if you want to detect as soon the reacyclerview reaches top check if(isRecyclerViewAtTop()) inside onScrolled method一旦到达顶部,这将在您松开手指时检测顶部,如果您想在 reacyclerview 到达顶部时立即检测,请在onScrolled方法中检查if(isRecyclerViewAtTop())

I have written a RecyclerViewHelper to know the recyclerview is at top or at bottom.我写了一个 RecyclerViewHelper 来知道 r​​ecyclerview 是在顶部还是底部。

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

} }

you can do this it's work for me你可以这样做,这对我有用

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

To find out if the RecyclerView is scrolled to bottom, you could reuse the methods used for the scrollbar.要确定 RecyclerView 是否滚动到底部,您可以重用用于滚动条的方法。

This is the calculation, for convenience written as a Kotlin extension function:这是计算,为了方便写成 Kotlin 扩展函数:

fun RecyclerView.isScrolledToBottom(): Boolean {
    val contentHeight = height - (paddingTop + paddingBottom)
    return computeVerticalScrollRange() == computeVerticalScrollOffset() + contentHeight
}

you can try with the OnTouchListener:您可以尝试使用 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;
}

If you're still looking for an answer in 2022, here you go:如果您仍在寻找 2022 年的答案,请看这里:

 mRecyclerView.setOnScrollChangeListener((view, i, i1, i2, i3) -> {
            if(!mRecyclerView.canScrollVertically(RecyclerView.FOCUS_DOWN)){
                 // reached the bottom of the list, load more data
            }
        });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 LinearLayoutManager 在 RecyclerView 中滚动到顶部 - Scroll to top in RecyclerView with LinearLayoutManager 如何知道用户是否滚动到列表视图/滚动视图的顶部或底部 - How to know if the user has scrolled to the top or bottom of a listview/scrollview 以编程方式如何知道recyclerview处于滚动位置是recyclerview的底部以执行以下功能 - How programmatically know that recyclerview is scrolled position is bottom of recyclerview to execute following function 如何知道edittext是否滚动到底部? - How to know if edittext is scrolled to bottom? 如何知道我们将 ScrollView 滚动到顶部 - How to know that we scrolled ScrollView to top 如何从RecyclerView ..获取LinearLayoutManager? - how to get LinearLayoutManager from RecyclerView..? RecyclerView LinearLayoutManager-如何在某个位置阻止滚动? - RecyclerView LinearLayoutManager - How to block scrolling at a certain position? 如何知道在RecyclerView中滚动了多少像素? - How to know how many pixels were scrolled in RecyclerView? android,当在viewpager中滚动recyclerview时,如何使父scrollview滚动到顶部 - android when recyclerview in a viewpager is scrolled, how to top parent scrollview scroll 如何检测用户何时滚动到RecyclerView中的最顶层项目 - How to detect when user have scrolled to the top most item in a RecyclerView
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM