下面列出了android.support.v7.widget.LinearLayoutManager#findFirstVisibleItemPosition ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* 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 onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
onPageScrollStateChanged(newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
int position = 0;
if (layoutManager instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
position = gridLayoutManager.findFirstVisibleItemPosition();
int row = gridLayoutManager.getSpanCount();
position = position / (row * mPageColumn);
} else if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
position = linearLayoutManager.findFirstVisibleItemPosition();
}
onPageSelected(position);
}
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearManager = (LinearLayoutManager) layoutManager;
int firstItemPosition = linearManager.findFirstVisibleItemPosition();
if(firstItemPosition == 0 || mContentListAdapter.getItemCount() == 0){
mRefreshLayout.setEnabled(true);
CFLog.e("V2MainFragment", "arrive top");
}
else{
mRefreshLayout.setEnabled(false);
}
}
}
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);
}
}
}
public void fetchMoreComplete(int newDataSize) {
if (getFetchMoreViewCount() == 0) {
return;
}
mFetching = false;
mFetchMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT);
notifyItemChanged(0);
// 定位到insert新消息前的top消息位置。必须移动,否则还在顶部,会继续fetch!!!
if (mRecyclerView != null) {
RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
// 只有LinearLayoutManager才有查找第一个和最后一个可见view位置的方法
if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearManager = (LinearLayoutManager) layoutManager;
//获取第一个可见view的位置
int firstItemPosition = linearManager.findFirstVisibleItemPosition();
if (firstItemPosition == 0) {
// 最顶部可见的View已经是FetchMoreView了,那么add数据&局部刷新后,要进行定位到上次的最顶部消息。
mRecyclerView.scrollToPosition(newDataSize + getFetchMoreViewCount());
}
} else {
mRecyclerView.scrollToPosition(newDataSize);
}
}
}
@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 onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
int itemCount = parent.getAdapter().getItemCount();
// center horizontally, calculate width and subtract half from center
float totalLength = mIndicatorItemLength * itemCount;
float paddingBetweenItems = Math.max(0, itemCount - 1) * mIndicatorItemPadding;
float indicatorTotalWidth = totalLength + paddingBetweenItems;
float indicatorStartX = (parent.getWidth() - indicatorTotalWidth) / 2F;
// center vertically in the allotted space
float indicatorPosY = parent.getHeight() - mIndicatorHeight / 2F;
drawInactiveIndicators(c, indicatorStartX, indicatorPosY, itemCount);
// find active page (which should be highlighted)
LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
int activePosition = layoutManager.findFirstVisibleItemPosition();
if (activePosition == RecyclerView.NO_POSITION) {
return;
}
// find offset of active page (if the user is scrolling)
final View activeChild = layoutManager.findViewByPosition(activePosition);
int left = activeChild.getLeft();
int width = activeChild.getWidth();
// on swipe the active item will be positioned from [-width, 0]
// interpolate offset for smooth animation
float progress = mInterpolator.getInterpolation(left * -1 / (float) width);
drawHighlights(c, indicatorStartX, indicatorPosY, activePosition, progress, itemCount);
}
@Override
public Varargs offset(U view, Varargs varargs) {
if (varargs.narg() > 1) {
return setScrollXY(view, varargs);
} else {
LinearLayoutManager layoutManager = (LinearLayoutManager) view.getLVRecyclerView().getLayoutManager();
int position = layoutManager.findFirstVisibleItemPosition();
View firstVisiableChildView = layoutManager.findViewByPosition(position);
int dy = (position) * firstVisiableChildView.getHeight() - firstVisiableChildView.getTop();
return varargsOf(valueOf(0), valueOf(DimenUtil.pxToDpi(dy)));
}
}
private ScrollState getScrollState() {
if (this.binding == null) {
return null;
}
LinearLayoutManager layoutManager = (LinearLayoutManager) this.binding.list.getLayoutManager();
int position = layoutManager.findFirstVisibleItemPosition();
final View view = this.binding.list.getChildAt(0);
if (view != null) {
return new ScrollState(position,view.getTop());
} else {
return new ScrollState(position, 0);
}
}
/**
* 获取当前fragment状态,在Demo中简单演示了RecyclerView的位置恢复
*/
public void getState() {
RecyclerView recyclerView = mMainFragment.getRecyclerView();
recyclerView.stopScroll();
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager){
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
int position = layoutManager.findFirstVisibleItemPosition();
int scroll = recyclerView.getChildAt(0).getTop();
addFragment(position,scroll);
}
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
int itemCount = parent.getAdapter().getItemCount();
// center horizontally, calculate width and subtract half from center
float totalLength = mIndicatorItemLength * itemCount;
float paddingBetweenItems = Math.max(0, itemCount - 1) * mIndicatorItemPadding;
float indicatorTotalWidth = totalLength + paddingBetweenItems;
float indicatorStartX = (parent.getWidth() - indicatorTotalWidth) / 2F;
// center vertically in the allotted space
float indicatorPosY = parent.getHeight() - mIndicatorHeight / 2F;
drawInactiveIndicators(c, indicatorStartX, indicatorPosY, itemCount);
// find active page (which should be highlighted)
LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
int activePosition = layoutManager.findFirstVisibleItemPosition();
if (activePosition == RecyclerView.NO_POSITION) {
return;
}
// find offset of active page (if the user is scrolling)
final View activeChild = layoutManager.findViewByPosition(activePosition);
int left = activeChild.getLeft();
int width = activeChild.getWidth();
// on swipe the active item will be positioned from [-width, 0]
// interpolate offset for smooth animation
float progress = mInterpolator.getInterpolation(left * -1 / (float) width);
drawHighlights(c, indicatorStartX, indicatorPosY, activePosition, progress, itemCount);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
int itemCount = parent.getAdapter().getItemCount();
// center horizontally, calculate width and subtract half from center
float totalLength = mIndicatorItemLength * itemCount;
float paddingBetweenItems = Math.max(0, itemCount - 1) * mIndicatorItemPadding;
float indicatorTotalWidth = totalLength + paddingBetweenItems;
float indicatorStartX = (parent.getWidth() - indicatorTotalWidth) / 2F;
// center vertically in the allotted space
float indicatorPosY = parent.getHeight() - mIndicatorHeight / 2F;
drawInactiveIndicators(c, indicatorStartX, indicatorPosY, itemCount);
// find active page (which should be highlighted)
LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
int activePosition = layoutManager.findFirstVisibleItemPosition();
if (activePosition == RecyclerView.NO_POSITION) {
return;
}
// find offset of active page (if the user is scrolling)
final View activeChild = layoutManager.findViewByPosition(activePosition);
int left = activeChild.getLeft();
int width = activeChild.getWidth();
// on swipe the active item will be positioned from [-width, 0]
// interpolate offset for smooth animation
float progress = mInterpolator.getInterpolation(left * -1 / (float) width);
drawHighlights(c, indicatorStartX, indicatorPosY, activePosition, progress, itemCount);
}
@Override
public void run() {
LinearLayoutManager manager = (LinearLayoutManager) mBannerListView.getLayoutManager();
int position = manager.findFirstVisibleItemPosition();
mBannerListView.smoothScrollToPosition(position + 1);
startSlideBanner();
}
public static int getScrollY(RecyclerView rv, int columnCount) {
View c = rv.getChildAt(0);
if (c == null) {
return 0;
}
LinearLayoutManager layoutManager = (LinearLayoutManager) rv.getLayoutManager();
int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
// Log.d("", "getScrollY() : firstVisiblePosition - " + firstVisiblePosition);
int scrollY = -(c.getTop());
// Log.d("", "getScrollY() : scrollY - " + scrollY);
if (columnCount > 1) {
sRecyclerViewItemHeights.put(firstVisiblePosition, c.getHeight() + QuickReturnUtils.dp2px(rv.getContext(), 8) / columnCount);
} else {
sRecyclerViewItemHeights.put(firstVisiblePosition, c.getHeight());
}
if (scrollY < 0)
scrollY = 0;
for (int i = 0; i < firstVisiblePosition; ++i) {
if (sRecyclerViewItemHeights.get(i) != null) // (this is a sanity check)
scrollY += sRecyclerViewItemHeights.get(i); //add all heights of the views that are gone
}
return scrollY;
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
int firstVisible = layoutManager.findFirstVisibleItemPosition();
int visibleCount = Math.abs(firstVisible - layoutManager.findLastVisibleItemPosition());
int itemCount = recyclerView.getAdapter().getItemCount();
if (firstVisible != lastFirstVisible || visibleCount != lastVisibleCount || itemCount != lastItemCount) {
scrollListener.onScroll(null, firstVisible, visibleCount, itemCount);
lastFirstVisible = firstVisible;
lastVisibleCount = visibleCount;
lastItemCount = itemCount;
}
}
@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;
}
@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 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;
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if(listener == null){
return;
}
IOnLoadMoreListener iOnLoadMoreListener = listener.get();
if(iOnLoadMoreListener!=null) {
iOnLoadMoreListener.onBeforeScroll(dx, dy);
if (layoutManager instanceof LinearLayoutManager) {
layoutManagerType = LAYOUT_MANAGER_TYPE.LINEAR;
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
mLastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
int firstVisible = linearLayoutManager.findFirstVisibleItemPosition();
iOnLoadMoreListener.notifyAppearStateChange(firstVisible
, mLastVisibleItemPosition
, dx
, dy);
} else if (layoutManager instanceof GridLayoutManager) {
layoutManagerType = LAYOUT_MANAGER_TYPE.GRID;
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
mLastVisibleItemPosition = gridLayoutManager.findLastVisibleItemPosition();
iOnLoadMoreListener.notifyAppearStateChange(gridLayoutManager.findFirstVisibleItemPosition()
, mLastVisibleItemPosition
, dx
, dy);
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
layoutManagerType = LAYOUT_MANAGER_TYPE.STAGGERED_GRID;
StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
int newSpanCount = staggeredGridLayoutManager.getSpanCount();
if (mLastPositions == null || newSpanCount != mLastPositions.length) {
mLastPositions = new int[newSpanCount];
}
if (mFirstPositions == null || newSpanCount != mFirstPositions.length) {
mFirstPositions = new int[newSpanCount];
}
//avoid crash of support-v7 original bug
try{
staggeredGridLayoutManager.findFirstVisibleItemPositions(mFirstPositions);
mFirstVisibleItemPosition = findMin(mFirstPositions);
staggeredGridLayoutManager.findLastVisibleItemPositions(mLastPositions);
mLastVisibleItemPosition = findMax(mLastPositions);
iOnLoadMoreListener.notifyAppearStateChange(
mFirstVisibleItemPosition
, mLastVisibleItemPosition
, dx
, dy);
}catch(Exception e){
e.printStackTrace();
WXLogUtils.e(e.toString());
}
} else {
throw new RuntimeException(
"Unsupported LayoutManager used. Valid ones are LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager");
}
}
}
private void processScrollListener() {
if (!(mLayoutManager instanceof LinearLayoutManager)) return;
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mLayoutManager;
int firstItemPosition;
firstItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
if (firstItemPosition == RecyclerView.NO_POSITION) return;
mIndexBar.setSelection(firstItemPosition);
if (!mSticyEnable) return;
ArrayList<EntityWrapper> list = mRealAdapter.getItems();
if (mStickyViewHolder != null && list.size() > firstItemPosition) {
EntityWrapper wrapper = list.get(firstItemPosition);
String wrapperTitle = wrapper.getIndexTitle();
if (EntityWrapper.TYPE_TITLE == wrapper.getItemType()) {
if (mLastInvisibleRecyclerViewItemView != null && mLastInvisibleRecyclerViewItemView.getVisibility() == INVISIBLE) {
mLastInvisibleRecyclerViewItemView.setVisibility(VISIBLE);
mLastInvisibleRecyclerViewItemView = null;
}
mLastInvisibleRecyclerViewItemView = linearLayoutManager.findViewByPosition(firstItemPosition);
if (mLastInvisibleRecyclerViewItemView != null) {
mLastInvisibleRecyclerViewItemView.setVisibility(INVISIBLE);
}
}
// hide -> show
if (wrapperTitle == null && mStickyViewHolder.itemView.getVisibility() == VISIBLE) {
mStickyTitle = null;
mStickyViewHolder.itemView.setVisibility(INVISIBLE);
} else {
stickyNewViewHolder(wrapperTitle);
}
// GirdLayoutManager
if (mLayoutManager instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) mLayoutManager;
if (firstItemPosition + gridLayoutManager.getSpanCount() < list.size()) {
for (int i = firstItemPosition + 1; i <= firstItemPosition + gridLayoutManager.getSpanCount(); i++) {
processScroll(linearLayoutManager, list, i, wrapperTitle);
}
}
} else { // LinearLayoutManager
if (firstItemPosition + 1 < list.size()) {
processScroll(linearLayoutManager, list, firstItemPosition + 1, wrapperTitle);
}
}
}
}