RecyclerView 有scrollToPosition和smoothScrollToPosition,其实它还具备锚点(Anchor)功能不过没提供给外部使用。锚点功能在activity切换前后时触发。
在activity切到后台时onSaveInstanceState将保存当前的滚动位置,滚动位置其实就是当前可见的第一个(或最后一个)View的position。来看看LinearLayoutManager是怎么实现的。
@Override
public Parcelable onSaveInstanceState() {
if (mPendingSavedState != null) {
return new SavedState(mPendingSavedState);
}
SavedState state = new SavedState();
if (getChildCount() > 0) {
ensureLayoutState();
boolean didLayoutFromEnd = mLastStackFromEnd ^ mShouldReverseLayout;
state.mAnchorLayoutFromEnd = didLayoutFromEnd;
if (didLayoutFromEnd) {
final View refChild = getChildClosestToEnd();
state.mAnchorOffset = mOrientationHelper.getEndAfterPadding() -
mOrientationHelper.getDecoratedEnd(refChild);
state.mAnchorPosition = getPosition(refChild);
} else {
final View refChild = getChildClosestToStart();
state.mAnchorPosition = getPosition(refChild);
state.mAnchorOffset = mOrientationHelper.getDecoratedStart(refChild) -
mOrientationHelper.getStartAfterPadding();
}
} else {
state.invalidateAnchor();
}
return state;
}
在activity切回时onRestoreInstanceState重新设置锚点。
@Override
public void onRestoreInstanceState(Parcelable state) {
if (state instanceof SavedState) {
mPendingSavedState = (SavedState) state;
requestLayout();
if (DEBUG) {
Log.d(TAG, "loaded saved state");
}
} else if (DEBUG) {
Log.d(TAG, "invalid saved state class");
}
}
实际锚点功能跟scrollToPosition的逻辑实现是基本相同的。那么这个锚点有什么作用呢?替换scrollToPosition,锚点和scrollToPosition都是直接跳转到制定位置,在scrollToPosition抽风的时候用smoothScrollToPosition在一些场合是很容易导致崩溃,用锚点就可了。