下面列出了怎么用android.support.v7.widget.RecyclerView.State的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
protected void onFinishInflate() {
mContent = findViewById(R.id.content);
mView = (WidgetsRecyclerView) findViewById(R.id.widgets_list_view);
mView.setAdapter(mAdapter);
// This extends the layout space so that preloading happen for the {@link RecyclerView}
mView.setLayoutManager(new LinearLayoutManager(getContext()) {
@Override
protected int getExtraLayoutSpace(State state) {
DeviceProfile grid = mLauncher.getDeviceProfile();
return super.getExtraLayoutSpace(state)
+ grid.availableHeightPx * PRELOAD_SCREEN_HEIGHT_MULTIPLE;
}
});
mPadding.set(getPaddingLeft(), getPaddingTop(), getPaddingRight(),
getPaddingBottom());
setScroller();
updateBackgroundAndPaddings();
}
int scrollBy(int dy, Recycler recycler, State state) {
int i = 0;
if (!(getChildCount() == 0 || dy == 0)) {
this.mLayoutState.mRecycle = true;
ensureLayoutState();
int layoutDirection = dy > 0 ? 1 : -1;
int absDy = Math.abs(dy);
updateLayoutState(layoutDirection, absDy, true, state);
int consumed = this.mLayoutState.mScrollingOffset + fill(recycler, this.mLayoutState, state, false);
if (consumed >= 0) {
if (absDy > consumed) {
i = layoutDirection * consumed;
} else {
i = dy;
}
this.mOrientationHelper.offsetChildren(-i);
this.mLayoutState.mLastScrollDelta = i;
}
}
return i;
}
@Override
public int scrollHorizontallyBy(int dx, Recycler recycler, RecyclerView.State state) {
if (DEBUG) Log.v(getTag(), "scrollHorizontallyBy " + dx);
if (!mLayoutEnabled || !hasDoneFirstLayout()) {
return 0;
}
saveContext(recycler, state);
int result;
if (mOrientation == HORIZONTAL) {
result = scrollDirectionPrimary(dx);
} else {
result = scrollDirectionSecondary(dx);
}
leaveContext();
return result;
}
private int fixLayoutStartGap(int startOffset, Recycler recycler, State state, boolean canOffsetChildren) {
int gap = startOffset - this.mOrientationHelper.getStartAfterPadding();
if (gap <= 0) {
return 0;
}
int fixOffset = -scrollBy(gap, recycler, state);
startOffset += fixOffset;
if (canOffsetChildren) {
gap = startOffset - this.mOrientationHelper.getStartAfterPadding();
if (gap > 0) {
this.mOrientationHelper.offsetChildren(-gap);
return fixOffset - gap;
}
}
return fixOffset;
}
@Override
public void onLayoutChildren(Recycler recycler, State state) {
super.onLayoutChildren(recycler, state);
if (mFocusStateRequest.notifyOnNextLayout) {
mFocusStateRequest.notifyOnNextLayout = false;
// If the notify has a animation, we should make sure the notify is later than
// RecyclerView's animation. So they will not conflict.
if (mFocusStateRequest.animate) {
postOnAnimation(new Runnable() {
@Override
public void run() {
// We wait for animation time begin and notify on next main loop,
// So we can sure the notify is follow the state change animation.
notifyAfterLayoutOnNextMainLoop();
}
});
} else {
requestNotifyChildrenStateChanged(mFocusStateRequest);
}
}
}
public void smoothScrollToPosition(RecyclerView recyclerView, State state, int position) {
LinearSmoothScroller scroller = new LinearSmoothScroller(recyclerView.getContext()) {
public PointF computeScrollVectorForPosition(int targetPosition) {
int direction = StaggeredGridLayoutManager.this.calculateScrollDirectionForPosition(targetPosition);
if (direction == 0) {
return null;
}
if (StaggeredGridLayoutManager.this.mOrientation == 0) {
return new PointF((float) direction, 0.0f);
}
return new PointF(0.0f, (float) direction);
}
};
scroller.setTargetPosition(position);
startSmoothScroll(scroller);
}
@Override
public int scrollVerticallyBy(int dy, Recycler recycler, RecyclerView.State state) {
if (DEBUG) Log.v(getTag(), "scrollVerticallyBy " + dy);
if (!mLayoutEnabled || !hasDoneFirstLayout()) {
return 0;
}
saveContext(recycler, state);
int result;
if (mOrientation == VERTICAL) {
result = scrollDirectionPrimary(dy);
} else {
result = scrollDirectionSecondary(dy);
}
leaveContext();
return result;
}
protected int getAnchorItemPosition(State state) {
final int itemCount = state.getItemCount();
int pendingPosition = getPendingScrollPosition();
if (pendingPosition != RecyclerView.NO_POSITION) {
if (pendingPosition < 0 || pendingPosition >= itemCount) {
pendingPosition = RecyclerView.NO_POSITION;
}
}
if (pendingPosition != RecyclerView.NO_POSITION) {
return pendingPosition;
} else if (getChildCount() > 0) {
return findFirstValidChildPosition(itemCount);
} else {
return 0;
}
}
private void fillGap(Direction direction, Recycler recycler, State state) {
final int childCount = getChildCount();
final int extraSpace = getExtraLayoutSpace(state);
final int firstPosition = getFirstVisiblePosition();
if (direction == Direction.END) {
fillAfter(firstPosition + childCount, recycler, state, extraSpace);
correctTooHigh(childCount, recycler, state);
} else {
fillBefore(firstPosition - 1, recycler, extraSpace);
correctTooLow(childCount, recycler, state);
}
}
private int computeScrollOffset(State state) {
boolean z = false;
if (getChildCount() == 0) {
return 0;
}
ensureLayoutState();
OrientationHelper orientationHelper = this.mOrientationHelper;
View findFirstVisibleChildClosestToStart = findFirstVisibleChildClosestToStart(!this.mSmoothScrollbarEnabled, true);
if (!this.mSmoothScrollbarEnabled) {
z = true;
}
return ScrollbarHelper.computeScrollOffset(state, orientationHelper, findFirstVisibleChildClosestToStart, findFirstVisibleChildClosestToEnd(z, true), this, this.mSmoothScrollbarEnabled, this.mShouldReverseLayout);
}
@Override
public int computeHorizontalScrollOffset(State state) {
if (getChildCount() == 0) {
return 0;
}
return getFirstVisiblePosition();
}
public View onFocusSearchFailed(View focused, int focusDirection, Recycler recycler, State state) {
resolveShouldLayoutReverse();
if (getChildCount() == 0) {
return null;
}
int layoutDir = convertFocusDirectionToLayoutDirection(focusDirection);
if (layoutDir == Integer.MIN_VALUE) {
return null;
}
View referenceChild;
ensureLayoutState();
if (layoutDir == -1) {
referenceChild = findReferenceChildClosestToStart(recycler, state);
} else {
referenceChild = findReferenceChildClosestToEnd(recycler, state);
}
if (referenceChild == null) {
return null;
}
View nextFocus;
ensureLayoutState();
updateLayoutState(layoutDir, (int) (MAX_SCROLL_FACTOR * ((float) this.mOrientationHelper.getTotalSpace())), false, state);
this.mLayoutState.mScrollingOffset = Integer.MIN_VALUE;
this.mLayoutState.mRecycle = false;
fill(recycler, this.mLayoutState, state, true);
if (layoutDir == -1) {
nextFocus = getChildClosestToStart();
} else {
nextFocus = getChildClosestToEnd();
}
if (nextFocus == referenceChild || !nextFocus.isFocusable()) {
return null;
}
return nextFocus;
}
private int scrollBy(int delta, Recycler recycler, State state) {
final int childCount = getChildCount();
if (childCount == 0 || delta == 0) {
return 0;
}
final int start = getStartWithPadding();
final int end = getEndWithPadding();
final int firstPosition = getFirstVisiblePosition();
final int totalSpace = getTotalSpace();
if (delta < 0) {
delta = Math.max(-(totalSpace - 1), delta);
} else {
delta = Math.min(totalSpace - 1, delta);
}
final boolean cannotScrollBackward = (firstPosition == 0 &&
mLayoutStart >= start && delta <= 0);
final boolean cannotScrollForward = (firstPosition + childCount == state.getItemCount() &&
mLayoutEnd <= end && delta >= 0);
if (cannotScrollForward || cannotScrollBackward) {
return 0;
}
offsetChildren(-delta);
final Direction direction = (delta > 0 ? Direction.END : Direction.START);
recycleChildrenOutOfBounds(direction, recycler);
final int absDelta = Math.abs(delta);
if (canAddMoreViews(Direction.START, start - absDelta) ||
canAddMoreViews(Direction.END, end + absDelta)) {
fillGap(direction, recycler, state);
}
return delta;
}
protected void onLayoutScrapList(Recycler recycler, State state) {
final int childCount = getChildCount();
if (childCount == 0 || state.isPreLayout() || !supportsPredictiveItemAnimations()) {
return;
}
final List<ViewHolder> scrapList = recycler.getScrapList();
fillFromScrapList(scrapList, Direction.START);
fillFromScrapList(scrapList, Direction.END);
}
@Override
public void checkAnchorInfo(RecyclerView.State state, VirtualLayoutManager.AnchorInfoWrapper anchorInfo, LayoutManagerHelper helper) {
if (state.getItemCount() > 0 ) {
GridRangeStyle rangeStyle = mRangeStyle.findRangeStyleByPosition(anchorInfo.position);
int span = rangeStyle.mSpanSizeLookup.getCachedSpanIndex(anchorInfo.position, rangeStyle.mSpanCount);
if (anchorInfo.layoutFromEnd) {
while (span < rangeStyle.mSpanCount - 1 && anchorInfo.position < getRange().getUpper()) {
anchorInfo.position++;
span = rangeStyle.mSpanSizeLookup.getCachedSpanIndex(anchorInfo.position, rangeStyle.mSpanCount);
}
} else {
while (span > 0 && anchorInfo.position > 0) {
anchorInfo.position--;
span = rangeStyle.mSpanSizeLookup.getCachedSpanIndex(anchorInfo.position, rangeStyle.mSpanCount);
}
}
mLayoutWithAnchor = true;
/*
if (anchorInfo.position == getRange().getLower() || anchorInfo.position == getRange().getUpper()) {
return;
}
boolean layoutInVertical = helper.getOrientation() == VERTICAL;
if (anchorInfo.layoutFromEnd) {
anchorInfo.coordinate += layoutInVertical ? mVGap : mHGap;
} else {
anchorInfo.coordinate -= layoutInVertical ? mVGap : mHGap;
}
*/
}
}
private int getSpanSize(SpanSizeLookup spanSizeLookup, RecyclerView.Recycler recycler, RecyclerView.State state, int pos) {
if (!state.isPreLayout()) {
return spanSizeLookup.getSpanSize(pos);
}
final int adapterPosition = recycler.convertPreLayoutPositionToPostLayout(pos);
if (adapterPosition == -1) {
return 0;
}
return spanSizeLookup.getSpanSize(adapterPosition);
}
private void assignSpans(GridRangeStyle rangeStyle, RecyclerView.Recycler recycler, RecyclerView.State state, int count,
int consumedSpanCount, boolean layingOutInPrimaryDirection, LayoutManagerHelper helper) {
int span, spanDiff, start, end, diff;
// make sure we traverse from min position to max position
if (layingOutInPrimaryDirection) {
start = 0;
end = count;
diff = 1;
} else {
start = count - 1;
end = -1;
diff = -1;
}
if (helper.getOrientation() == VERTICAL && helper.isDoLayoutRTL()) { // start from last span
span = consumedSpanCount - 1;
spanDiff = -1;
} else {
span = 0;
spanDiff = 1;
}
for (int i = start; i != end; i += diff) {
View view = rangeStyle.mSet[i];
int spanSize = getSpanSize(rangeStyle.mSpanSizeLookup, recycler, state, helper.getPosition(view));
if (spanDiff == -1 && spanSize > 1) {
rangeStyle.mSpanIndices[i] = span - (spanSize - 1);
} else {
rangeStyle.mSpanIndices[i] = span;
}
span += spanDiff * spanSize;
}
}
@Override
public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state,
LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper) {
mTempLayoutHelper = helper;
doLayoutView(recycler, state, layoutState, result, helper);
mTempLayoutHelper = null;
}
@Override
public
@NonNull
ItemHolderInfo recordPreLayoutInformation(@NonNull State state,
@NonNull ViewHolder viewHolder, @AdapterChanges int changeFlags,
@NonNull List<Object> payloads) {
final ItemHolderInfo itemHolderInfo = super.recordPreLayoutInformation(state, viewHolder,
changeFlags, payloads);
if (itemHolderInfo instanceof PayloadItemHolderInfo) {
((PayloadItemHolderInfo) itemHolderInfo).setPayloads(payloads);
}
return itemHolderInfo;
}
@Override
public void onDraw(Canvas c, RecyclerView parent, State state) {
/**画item底部的分割线*/
drawVertical(c, parent);
/**画item右边的分割线*/
drawHorizontal(c, parent);
}
private void fillSpecific(int position, Recycler recycler, State state) {
if (state.getItemCount() == 0) {
return;
}
makeAndAddView(position, Direction.END, recycler);
final int extraSpaceBefore;
final int extraSpaceAfter;
final int extraSpace = getExtraLayoutSpace(state);
if (state.getTargetScrollPosition() < position) {
extraSpaceAfter = 0;
extraSpaceBefore = extraSpace;
} else {
extraSpaceAfter = extraSpace;
extraSpaceBefore = 0;
}
fillBefore(position - 1, recycler, extraSpaceBefore);
// This will correct for the top of the first view not
// touching the top of the parent.
adjustViewsStartOrEnd();
fillAfter(position + 1, recycler, state, extraSpaceAfter);
correctTooHigh(getChildCount(), recycler, state);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, State state)
{
drawHorizontal(c, parent);
drawVertical(c, parent);
}
public void onDraw(Canvas c, RecyclerView parent, State state) {
this.mOverdrawChildPosition = -1;
float dx = 0.0f;
float dy = 0.0f;
if (this.mSelected != null) {
getSelectedDxDy(this.mTmpPosition);
dx = this.mTmpPosition[0];
dy = this.mTmpPosition[1];
}
this.mCallback.onDraw(c, parent, this.mSelected, this.mRecoverAnimations, this.mActionState, dx, dy);
}
static int computeScrollOffset(State state, OrientationHelper orientation, View startChild, View endChild, LayoutManager lm, boolean smoothScrollbarEnabled, boolean reverseLayout) {
if (lm.getChildCount() == 0 || state.getItemCount() == 0 || startChild == null || endChild == null) {
return 0;
}
int itemsBefore = reverseLayout ? Math.max(0, (state.getItemCount() - Math.max(lm.getPosition(startChild), lm.getPosition(endChild))) - 1) : Math.max(0, Math.min(lm.getPosition(startChild), lm.getPosition(endChild)));
if (!smoothScrollbarEnabled) {
return itemsBefore;
}
return Math.round((((float) itemsBefore) * (((float) Math.abs(orientation.getDecoratedEnd(endChild) - orientation.getDecoratedStart(startChild))) / ((float) (Math.abs(lm.getPosition(startChild) - lm.getPosition(endChild)) + 1)))) + ((float) (orientation.getStartAfterPadding() - orientation.getDecoratedStart(startChild))));
}
static int computeScrollExtent(State state, OrientationHelper orientation, View startChild, View endChild, LayoutManager lm, boolean smoothScrollbarEnabled) {
if (lm.getChildCount() == 0 || state.getItemCount() == 0 || startChild == null || endChild == null) {
return 0;
}
if (!smoothScrollbarEnabled) {
return Math.abs(lm.getPosition(startChild) - lm.getPosition(endChild)) + 1;
}
return Math.min(orientation.getTotalSpace(), orientation.getDecoratedEnd(endChild) - orientation.getDecoratedStart(startChild));
}
static int computeScrollRange(State state, OrientationHelper orientation, View startChild, View endChild, LayoutManager lm, boolean smoothScrollbarEnabled) {
if (lm.getChildCount() == 0 || state.getItemCount() == 0 || startChild == null || endChild == null) {
return 0;
}
if (!smoothScrollbarEnabled) {
return state.getItemCount();
}
return (int) ((((float) (orientation.getDecoratedEnd(endChild) - orientation.getDecoratedStart(startChild))) / ((float) (Math.abs(lm.getPosition(startChild) - lm.getPosition(endChild)) + 1))) * ((float) state.getItemCount()));
}
public int getRowCountForAccessibility(Recycler recycler, State state) {
if (this.mOrientation == 0) {
return this.mSpanCount;
}
if (state.getItemCount() < 1) {
return 0;
}
return getSpanGroupIndex(recycler, state, state.getItemCount() - 1) + 1;
}
public void onLayoutChildren(Recycler recycler, State state) {
if (state.isPreLayout()) {
cachePreLayoutSpanMapping();
}
super.onLayoutChildren(recycler, state);
clearPreLayoutSpanMappingCache();
if (!state.isPreLayout()) {
this.mPendingSpanCountChange = false;
}
}
private void fillAfter(int position, Recycler recycler, State state, int extraSpace) {
final int limit = getEndWithPadding() + extraSpace;
final int itemCount = state.getItemCount();
while (canAddMoreViews(Direction.END, limit) && position < itemCount) {
makeAndAddView(position, Direction.END, recycler);
position++;
}
}
View findReferenceChild(Recycler recycler, State state, int start, int end, int itemCount) {
ensureLayoutState();
View invalidMatch = null;
View outOfBoundsMatch = null;
int boundsStart = this.mOrientationHelper.getStartAfterPadding();
int boundsEnd = this.mOrientationHelper.getEndAfterPadding();
int diff = end > start ? 1 : -1;
for (int i = start; i != end; i += diff) {
View childAt = getChildAt(i);
int position = getPosition(childAt);
if (position >= 0 && position < itemCount && getSpanIndex(recycler, state, position) == 0) {
if (((android.support.v7.widget.RecyclerView.LayoutParams) childAt.getLayoutParams()).isItemRemoved()) {
if (invalidMatch == null) {
invalidMatch = childAt;
}
} else if (this.mOrientationHelper.getDecoratedStart(childAt) < boundsEnd && this.mOrientationHelper.getDecoratedEnd(childAt) >= boundsStart) {
return childAt;
} else {
if (outOfBoundsMatch == null) {
outOfBoundsMatch = childAt;
}
}
}
}
if (outOfBoundsMatch == null) {
outOfBoundsMatch = invalidMatch;
}
return outOfBoundsMatch;
}