[英]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:方向整数:
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,使用RecycleView的addOnScrollListener ,您可以找到垂直 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 来知道 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;
}
} }
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.