下面列出了android.support.v7.widget.LinearLayoutManager#findLastVisibleItemPosition ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* 滑动监听
* @param recyclerView
* @param dx
* @param dy
*/
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearLayout = (LinearLayoutManager) layoutManager;
int mLastChildPosition = linearLayout.findLastVisibleItemPosition();
int itemTotalCount = linearLayout.getItemCount();
View lastChildView = linearLayout.getChildAt(linearLayout.getChildCount() - 1);
int lastChildBottom = lastChildView.getBottom();
int recyclerBottom = getBottom();
if (mLastChildPosition == itemTotalCount - 1 && lastChildBottom == recyclerBottom) {
if (isCanLoadMore && listener != null) {
//业务代码
listener.loadMore();
}
}
}
}
private void moveToPosition(LinearLayoutManager layoutManager, RecyclerView recyclerView, int position) {
// 第一个可见的view的位置
int firstItem = layoutManager.findFirstVisibleItemPosition();
// 最后一个可见的view的位置
int lastItem = layoutManager.findLastVisibleItemPosition();
if (position <= firstItem) {
// 如果跳转位置firstItem 之前(滑出屏幕的情况),就smoothScrollToPosition可以直接跳转,
recyclerView.smoothScrollToPosition(position);
} else if (position <= lastItem) {
// 跳转位置在firstItem 之后,lastItem 之间(显示在当前屏幕),smoothScrollBy来滑动到指定位置
int top = recyclerView.getChildAt(position - firstItem).getTop();
recyclerView.smoothScrollBy(0, top);
} else {
// 如果要跳转的位置在lastItem 之后,则先调用smoothScrollToPosition将要跳转的位置滚动到可见位置
// 再通过onScrollStateChanged控制再次调用当前moveToPosition方法,执行上一个判断中的方法
recyclerView.smoothScrollToPosition(position);
scrollToPosition = position;
canScroll = true;
}
}
private void moveToPosition(int position) {
if (position > data.size())
return;
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
int first = layoutManager.findFirstVisibleItemPosition();
int end = layoutManager.findLastVisibleItemPosition();
if (first == -1 || end == -1)
return;
if (position <= first) {
layoutManager.scrollToPosition(position);
} else if (position >= end) {
isMove = true;
scrollPosition = position;
layoutManager.smoothScrollToPosition(recyclerView, null, position);
} else {//中间部分
int n = position - layoutManager.findFirstVisibleItemPosition();
if (n > 0 && n < data.size()) {
int top = layoutManager.findViewByPosition(position).getTop();
recyclerView.scrollBy(0, top);
}
}
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState != RecyclerView.SCROLL_STATE_IDLE
|| !(recyclerView.getLayoutManager() instanceof LinearLayoutManager)
|| recyclerView.getChildCount() < AVAILABLE) {
return;
}
final LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager();
final int totalItemCount = recyclerView.getAdapter().getItemCount();
final int lastVisibleItemPosition = manager.findLastVisibleItemPosition();
if (lastVisibleItemPosition == totalItemCount - 1) {
mTrack.logEvent(TrackCons.Main.SCROLL_BOTTOM);
}
}
/**
* Calculates the distance between the RecyclerView's anchor, either the start, center or end,
* and the View which is closest to the anchor.
*
* @return The distance between RecyclerView anchor and View closest to anchor
*/
private int calculateSnapDistance() {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
int parentAnchor = getParentAnchor(orientation, anchor);
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View currentViewClosestToAnchor = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
int currentViewClosestToAnchorDistance = parentAnchor - getViewAnchor(currentViewClosestToAnchor, orientation, anchor);
for(int i = firstVisibleItemPosition + 1; i <= lastVisibleItemPosition; i++) {
View view = linearLayoutManager.findViewByPosition(i);
int distanceToAnchor = parentAnchor - getViewAnchor(view, orientation, anchor);
if (Math.abs(distanceToAnchor) < Math.abs(currentViewClosestToAnchorDistance)) {
currentViewClosestToAnchorDistance = distanceToAnchor;
}
}
return currentViewClosestToAnchorDistance;
}
@Override
public void check(View view, NoMatchingViewException noViewFoundException) {
if (noViewFoundException != null) {
throw noViewFoundException;
}
RecyclerView recyclerView = (RecyclerView) view;
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
int firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
int lastVisibleItem = layoutManager.findLastVisibleItemPosition();
boolean indexInRange = firstVisibleItem <= index && index <= lastVisibleItem;
if ((shouldBeVisible && !indexInRange) || (!shouldBeVisible && indexInRange)) {
String errorMessage = "expected item " + index + " to " +
(shouldBeVisible ? "" : "not") + " be visible, but was" +
(indexInRange ? "" : " not") + " visible";
throw new AssertionError(errorMessage);
}
}
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
BaseQuickAdapter adapter = (BaseQuickAdapter) recyclerView.getAdapter();
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
if (newState == RecyclerView.SCROLL_STATE_IDLE && lastVisibleItemPosition + 1 == layoutManager.getItemCount() && adapter.isHasMore()) {
//当已经滑到最后一条的时候
adapter.isLoadingMore();
}
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
// If you tap on the phone while the RecyclerView is scrolling it will stop in the middle.
// This code fixes this. This code is not strictly necessary but it improves the behaviour.
if (state == SCROLL_STATE_IDLE) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
// int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
int screenWidth = getMeasuredWidth();
// views on the screen
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
// distance we need to scroll
int leftMargin = (screenWidth - lastView.getWidth()) / 2;
int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
int leftEdge = lastView.getLeft();
int rightEdge = firstView.getRight();
int scrollDistanceLeft = leftEdge - leftMargin;
int scrollDistanceRight = rightMargin - rightEdge;
if (leftEdge > screenWidth / 2) {
smoothScrollBy(-scrollDistanceRight, 0);
} else if (rightEdge < screenWidth / 2) {
smoothScrollBy(scrollDistanceLeft, 0);
}
}
}
@Override
public void run() {
if (getLayoutManager() instanceof LinearLayoutManager && isFirstLayoutPassed() && getExpandableAdapter()!=null) {
LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
int first = layoutManager.findFirstVisibleItemPosition();
int last = layoutManager.findLastVisibleItemPosition();
getAdapter().notifyItemRangeChanged(first, last);
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
if (layoutManager == null)
throw new IllegalStateException("Can't handle scrolling without a LayoutManager");
int lastVisibleItem = layoutManager.findLastVisibleItemPosition();
if (!loading && layoutManager.getItemCount() <= (lastVisibleItem + 5)) {
startLoading();
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if(!loadMoreEnable || !canLoadMore || isLoading ||
!NetHelper.INSTANCE.getNetEnabled()) return;
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
//only LinearLayoutManager can find last visible
if(layoutManager instanceof LinearLayoutManager){
LinearLayoutManager linearManager = (LinearLayoutManager) layoutManager;
int lastPosition = linearManager.findLastVisibleItemPosition();
if(lastPosition == adapter.getItemCount() - 1){
onLoadMore(++curPage);
}
}
}
RecyclerView.OnScrollListener getScrollToBottomListener(final LinearLayoutManager linearLayoutManager) {
return new RecyclerView.OnScrollListener() {
@Override public void onScrolled(RecyclerView rv, int dx, int dy) {
boolean isBottom = linearLayoutManager.findLastVisibleItemPosition() == (feedsList.size() - 1);
if (!refreshLayout.isRefreshing() && isBottom) {
refreshLayout.setRefreshing(true);
nextPage++;
initGankData(nextPage, false);
}
}
};
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
int lastVisibleItem = layoutManager.findLastVisibleItemPosition();
int totalItemCount = layoutManager.getItemCount();
//lastVisibleItem >= totalItemCount - 1 表示剩下1个item自动加载
// dy>0 表示向下滑动
if (lastVisibleItem >= totalItemCount - 1 && dy > 0) {
onListLoadMore();
}
}
@Nullable
private View findStartView(RecyclerView.LayoutManager layoutManager,
@NonNull OrientationHelper helper) {
if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
boolean reverseLayout = linearLayoutManager.getReverseLayout();
int firstChild = reverseLayout ? linearLayoutManager.findLastVisibleItemPosition()
: linearLayoutManager.findFirstVisibleItemPosition();
int offset = 1;
if (layoutManager instanceof GridLayoutManager) {
offset += ((GridLayoutManager) layoutManager).getSpanCount() - 1;
}
if (firstChild == RecyclerView.NO_POSITION) {
return null;
}
View child = layoutManager.findViewByPosition(firstChild);
float visibleWidth;
if (isRtlHorizontal) {
visibleWidth = (float) (helper.getTotalSpace() - helper.getDecoratedStart(child))
/ helper.getDecoratedMeasurement(child);
} else {
visibleWidth = (float) helper.getDecoratedEnd(child)
/ helper.getDecoratedMeasurement(child);
}
boolean endOfList;
if (!reverseLayout) {
endOfList = ((LinearLayoutManager) layoutManager)
.findLastCompletelyVisibleItemPosition()
== layoutManager.getItemCount() - 1;
} else {
endOfList = ((LinearLayoutManager) layoutManager)
.findFirstCompletelyVisibleItemPosition()
== 0;
}
if (visibleWidth > 0.5f && !endOfList) {
return child;
} else if (snapLastItem && endOfList) {
return child;
} else if (endOfList) {
return null;
} else {
return reverseLayout ? layoutManager.findViewByPosition(firstChild - offset)
: layoutManager.findViewByPosition(firstChild + offset);
}
}
return null;
}
@Nullable
private View findEndView(RecyclerView.LayoutManager layoutManager,
@NonNull OrientationHelper helper) {
if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
boolean reverseLayout = linearLayoutManager.getReverseLayout();
int lastChild = reverseLayout ? linearLayoutManager.findFirstVisibleItemPosition()
: linearLayoutManager.findLastVisibleItemPosition();
int offset = 1;
if (layoutManager instanceof GridLayoutManager) {
offset += ((GridLayoutManager) layoutManager).getSpanCount() - 1;
}
if (lastChild == RecyclerView.NO_POSITION) {
return null;
}
View child = layoutManager.findViewByPosition(lastChild);
float visibleWidth;
if (isRtlHorizontal) {
visibleWidth = (float) helper.getDecoratedEnd(child)
/ helper.getDecoratedMeasurement(child);
} else {
visibleWidth = (float) (helper.getTotalSpace() - helper.getDecoratedStart(child))
/ helper.getDecoratedMeasurement(child);
}
boolean startOfList;
if (!reverseLayout) {
startOfList = ((LinearLayoutManager) layoutManager)
.findFirstCompletelyVisibleItemPosition() == 0;
} else {
startOfList = ((LinearLayoutManager) layoutManager)
.findLastCompletelyVisibleItemPosition()
== layoutManager.getItemCount() - 1;
}
if (visibleWidth > 0.5f && !startOfList) {
return child;
} else if (snapLastItem && startOfList) {
return child;
} else if (startOfList) {
return null;
} else {
return reverseLayout ? layoutManager.findViewByPosition(lastChild + offset)
: layoutManager.findViewByPosition(lastChild - offset);
}
}
return null;
}
private boolean shouldLoadMore() {
LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
return layoutManager.findLastVisibleItemPosition() == mRecyclerView.getAdapter().getItemCount() - 1;
}
@Override
public boolean fling(int velocityX, int velocityY) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
// int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
int screenWidth = getMeasuredWidth();
// views on the screen
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
// distance we need to scroll
int leftMargin = (screenWidth - lastView.getWidth()) / 2;
int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
int leftEdge = lastView.getLeft();
int rightEdge = firstView.getRight();
int scrollDistanceLeft = leftEdge - leftMargin;
int scrollDistanceRight = rightMargin - rightEdge;
if (Math.abs(velocityX) < 1000) {
// The fling is slow -> stay at the current page if we are less than half through,
// or go to the next page if more than half through
if (leftEdge > screenWidth / 2) {
// go to next page
smoothScrollBy(-scrollDistanceRight, 0);
} else if (rightEdge < screenWidth / 2) {
// go to next page
smoothScrollBy(scrollDistanceLeft, 0);
} else {
// stay at current page
if (velocityX > 0) {
smoothScrollBy(-scrollDistanceRight, 0);
} else {
smoothScrollBy(scrollDistanceLeft, 0);
}
}
return true;
} else {
// The fling is fast -> go to next page
if (velocityX > 0) {
smoothScrollBy(scrollDistanceLeft, 0);
} else {
smoothScrollBy(-scrollDistanceRight, 0);
}
return true;
}
}
@Nullable
private View findStartView(RecyclerView.LayoutManager layoutManager,
@NonNull OrientationHelper helper) {
if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
boolean reverseLayout = linearLayoutManager.getReverseLayout();
int firstChild = reverseLayout ? linearLayoutManager.findLastVisibleItemPosition()
: linearLayoutManager.findFirstVisibleItemPosition();
int offset = 1;
if (layoutManager instanceof GridLayoutManager) {
offset += ((GridLayoutManager) layoutManager).getSpanCount() - 1;
}
if (firstChild == RecyclerView.NO_POSITION) {
return null;
}
View child = layoutManager.findViewByPosition(firstChild);
float visibleWidth;
if (isRtlHorizontal) {
visibleWidth = (float) (helper.getTotalSpace() - helper.getDecoratedStart(child))
/ helper.getDecoratedMeasurement(child);
} else {
visibleWidth = (float) helper.getDecoratedEnd(child)
/ helper.getDecoratedMeasurement(child);
}
boolean endOfList;
if (!reverseLayout) {
endOfList = ((LinearLayoutManager) layoutManager)
.findLastCompletelyVisibleItemPosition()
== layoutManager.getItemCount() - 1;
} else {
endOfList = ((LinearLayoutManager) layoutManager)
.findFirstCompletelyVisibleItemPosition()
== 0;
}
if (visibleWidth > 0.5f && !endOfList) {
return child;
} else if (snapLastItem && endOfList) {
return child;
} else if (endOfList) {
return null;
} else {
return reverseLayout ? layoutManager.findViewByPosition(firstChild - offset)
: layoutManager.findViewByPosition(firstChild + offset);
}
}
return null;
}
private boolean isBottom(int dx, int dy) {
LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
int lastVisibleItem = layoutManager.findLastVisibleItemPosition();
int totalItemCount = layoutManager.getItemCount();
return lastVisibleItem >= totalItemCount - 4 && dy > 0;
}
@Nullable
private View findEndView(RecyclerView.LayoutManager layoutManager,
@NonNull OrientationHelper helper) {
if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
boolean reverseLayout = linearLayoutManager.getReverseLayout();
int lastChild = reverseLayout ? linearLayoutManager.findFirstVisibleItemPosition()
: linearLayoutManager.findLastVisibleItemPosition();
int offset = 1;
if (layoutManager instanceof GridLayoutManager) {
offset += ((GridLayoutManager) layoutManager).getSpanCount() - 1;
}
if (lastChild == RecyclerView.NO_POSITION) {
return null;
}
View child = layoutManager.findViewByPosition(lastChild);
float visibleWidth;
if (isRtlHorizontal) {
visibleWidth = (float) helper.getDecoratedEnd(child)
/ helper.getDecoratedMeasurement(child);
} else {
visibleWidth = (float) (helper.getTotalSpace() - helper.getDecoratedStart(child))
/ helper.getDecoratedMeasurement(child);
}
boolean startOfList;
if (!reverseLayout) {
startOfList = ((LinearLayoutManager) layoutManager)
.findFirstCompletelyVisibleItemPosition() == 0;
} else {
startOfList = ((LinearLayoutManager) layoutManager)
.findLastCompletelyVisibleItemPosition()
== layoutManager.getItemCount() - 1;
}
if (visibleWidth > 0.5f && !startOfList) {
return child;
} else if (snapLastItem && startOfList) {
return child;
} else if (startOfList) {
return null;
} else {
return reverseLayout ? layoutManager.findViewByPosition(lastChild + offset)
: layoutManager.findViewByPosition(lastChild - offset);
}
}
return null;
}