下面列出了android.support.v7.widget.LinearLayoutManager#findViewByPosition ( ) 实例代码,或者点击链接到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;
}
/**
* RecyclerView转换成bitmap
*
* @param recyclerView
* @return
*/
public static List<BitmapWithHeight> getWholeRecyclerViewItemsToBitmap(final RecyclerView recyclerView) {
List<BitmapWithHeight> list = new ArrayList<>();
if (recyclerView == null || recyclerView.getAdapter() == null) {
return list;
}
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager();
if (manager.getOrientation() == LinearLayoutManager.VERTICAL) {
int count = manager.getItemCount();
LogUtils.w(count + "");
for (int i = 0; i < count; i++) {
View childView = manager.findViewByPosition(i);
// TODO: 1/25/16 childView不可见部分为null,无法截长图
if (childView != null) {
list.add(getSimpleViewToBitmap(childView, recyclerView.getMeasuredWidth()));
}
}
} else {
list.add(getSimpleViewToBitmap(recyclerView, recyclerView.getMeasuredWidth()));
}
}
return list;
}
private void processScroll(LinearLayoutManager layoutManager, ArrayList<EntityWrapper> list, int position, String title) {
EntityWrapper nextWrapper = list.get(position);
View nextTitleView = layoutManager.findViewByPosition(position);
if (nextTitleView == null) return;
if (nextWrapper.getItemType() == EntityWrapper.TYPE_TITLE) {
if (nextTitleView.getTop() <= mStickyViewHolder.itemView.getHeight() && title != null) {
mStickyViewHolder.itemView.setTranslationY(nextTitleView.getTop() - mStickyViewHolder.itemView.getHeight());
}
if (INVISIBLE == nextTitleView.getVisibility()) {
//特殊情况:手指向下滑动的时候,需要及时把成为第二个可见View的TitleView设置Visible,
// 这样才能配合StickyView制造两个TitleView切换的动画。
nextTitleView.setVisibility(VISIBLE);
}
return;
} else if (mStickyViewHolder.itemView.getTranslationY() != 0) {
mStickyViewHolder.itemView.setTranslationY(0);
}
return;
}
@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)));
}
}
/**
* 水平滑动了多少px
*
* @return int px
*/
private int getScrollXDistance() {
LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
int position = layoutManager.findFirstVisibleItemPosition();
View firstVisibleChildView = layoutManager.findViewByPosition(position);
int itemWidth = firstVisibleChildView.getWidth();
return (position) * itemWidth - firstVisibleChildView.getLeft();
}
@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);
}
public int findRealFirstVisibleItemPosition(int pos) {
View view;
final LinearLayoutManager linearLayoutManager =
(LinearLayoutManager) mRecyclerView.getLayoutManager();
while (pos > 0) {
view = linearLayoutManager.findViewByPosition(pos - 1);
if (view == null) {
break;
}
pos = pos - 1;
}
return pos;
}
public static void scrollToPosition(RecyclerView recyclerView, int position) {
LinearLayoutManager lm = (LinearLayoutManager) recyclerView.getLayoutManager();
int recyclerWidth = recyclerView.getWidth();
View itemView = lm.findViewByPosition(position);
if (itemView != null) {
int viewWidth = itemView.getWidth();
lm.scrollToPositionWithOffset(position, -(recyclerWidth - viewWidth) / 2);
}
}
@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 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;
}
}
private void updateDragPositionAndScroll() {
View view = findChildView(mDragItem.getX(), mDragItem.getY());
int newPos = getChildLayoutPosition(view);
if (newPos == NO_POSITION) {
return;
}
LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
if (shouldChangeItemPosition(newPos)) {
if (mDisableReorderWhenDragging) {
mAdapter.setDropTargetId(mAdapter.getItemId(newPos));
mAdapter.notifyDataSetChanged();
} else {
changePosition = true;
int pos = layoutManager.findFirstVisibleItemPosition();
View posView = layoutManager.findViewByPosition(pos);
mAdapter.changeItemPosition(mDragItemPosition, newPos);
mDragItemPosition = newPos;
// Since notifyItemMoved scrolls the list we need to scroll back to where we were after the position change.
if (layoutManager.getOrientation() == LinearLayoutManager.VERTICAL) {
int topMargin = ((MarginLayoutParams) posView.getLayoutParams()).topMargin;
layoutManager.scrollToPositionWithOffset(pos, posView.getTop() - topMargin);
} else {
int leftMargin = ((MarginLayoutParams) posView.getLayoutParams()).leftMargin;
layoutManager.scrollToPositionWithOffset(pos, posView.getLeft() - leftMargin);
}
}
}
boolean lastItemReached = false;
boolean firstItemReached = false;
int top = mClipToPadding ? getPaddingTop() : 0;
int bottom = mClipToPadding ? getHeight() - getPaddingBottom() : getHeight();
int left = mClipToPadding ? getPaddingLeft() : 0;
int right = mClipToPadding ? getWidth() - getPaddingRight() : getWidth();
ViewHolder lastChild = findViewHolderForLayoutPosition(mAdapter.getItemCount() - 1);
ViewHolder firstChild = findViewHolderForLayoutPosition(0);
// Check if first or last item has been reached
if (layoutManager.getOrientation() == LinearLayoutManager.VERTICAL) {
if (lastChild != null && lastChild.itemView.getBottom() <= bottom) {
lastItemReached = true;
}
if (firstChild != null && firstChild.itemView.getTop() >= top) {
firstItemReached = true;
}
} else {
if (lastChild != null && lastChild.itemView.getRight() <= right) {
lastItemReached = true;
}
if (firstChild != null && firstChild.itemView.getLeft() >= left) {
firstItemReached = true;
}
}
// Start auto scroll if at the edge
if (layoutManager.getOrientation() == LinearLayoutManager.VERTICAL) {
if (mDragItem.getY() > getHeight() - view.getHeight() / 2 && !lastItemReached) {
mAutoScroller.startAutoScroll(AutoScroller.ScrollDirection.UP);
} else if (mDragItem.getY() < view.getHeight() / 2 && !firstItemReached) {
mAutoScroller.startAutoScroll(AutoScroller.ScrollDirection.DOWN);
} else {
mAutoScroller.stopAutoScroll();
}
} else {
if (mDragItem.getX() > getWidth() - view.getWidth() / 2 && !lastItemReached) {
mAutoScroller.startAutoScroll(AutoScroller.ScrollDirection.LEFT);
} else if (mDragItem.getX() < view.getWidth() / 2 && !firstItemReached) {
mAutoScroller.startAutoScroll(AutoScroller.ScrollDirection.RIGHT);
} else {
mAutoScroller.stopAutoScroll();
}
}
}
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);
}
}
}
}
/**
* Finds the position of the View which is closest to the RecyclerView's anchor, either the
* RecyclerView's start, center or end
*
* @return The position of the View closest the to RecyclerView's anchor
*/
private int calculateSnapViewPosition() {
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);
int currentViewClosestToAnchorPosition = firstVisibleItemPosition;
for(int i = firstVisibleItemPosition + 1; i <= lastVisibleItemPosition; i++) {
View view = linearLayoutManager.findViewByPosition(i);
int distanceToCenter = parentAnchor - getViewAnchor(view, orientation, anchor);
if (Math.abs(distanceToCenter) < Math.abs(currentViewClosestToAnchorDistance)) {
currentViewClosestToAnchorPosition = i;
currentViewClosestToAnchorDistance = distanceToCenter;
}
}
return currentViewClosestToAnchorPosition;
}