编辑:要恢复完全相同的明显位置,就像让它看起来完全一样,我们需要做一些不同的事情(见下文如何恢复准确的 scrollY 值):
像这样保存位置和偏移量:
LinearLayoutManager manager = (LinearLayoutManager) mRecycler.getLayoutManager();
int firstItem = manager.findFirstVisibleItemPosition();
View firstItemView = manager.findViewByPosition(firstItem);
float topOffset = firstItemView.getTop();
outState.putInt(ARGS_SCROLL_POS, firstItem);
outState.putFloat(ARGS_SCROLL_OFFSET, topOffset);
然后像这样恢复滚动:
LinearLayoutManager manager = (LinearLayoutManager) mRecycler.getLayoutManager();
manager.scrollToPositionWithOffset(mStatePos, (int) mStateOffset);
这会将列表恢复到其确切的明显位置。很明显,因为它在用户看来是一样的,但它不会具有相同的 scrollY 值(因为横向/纵向布局尺寸可能存在差异)。
请注意,这只适用于 LinearLayoutManager。
--- 下面是如何恢复精确的scrollY,这可能会使列表看起来不同 ---
-
像这样应用 OnScrollListener:
private int mScrollY;
private RecyclerView.OnScrollListener mTotalScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
mScrollY += dy;
}
};
这将始终将准确的滚动位置存储在 mScrollY 中。
将此变量存储在您的 Bundle 中,并在状态恢复中将其恢复到不同的变量,我们将其称为 mStateScrollY。
-
在状态恢复和之后,您的 RecyclerView 已重置其所有数据,并使用以下内容重置滚动:
mRecyclerView.scrollBy(0, mStateScrollY);
就是这样。
注意,将滚动恢复到不同的变量,这很重要,因为 OnScrollListener 将使用 .scrollBy() 调用,随后会将 mScrollY 设置为存储在 mStateScrollY 中的值。如果您不这样做,mScrollY 将具有双倍滚动值(因为 OnScrollListener 与增量一起使用,而不是绝对滚动)。
活动中的状态保存可以这样实现:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(ARGS_SCROLL_Y, mScrollY);
}
并在你的 onCreate() 中恢复调用:
if(savedState != null){
mStateScrollY = savedState.getInt(ARGS_SCROLL_Y, 0);
}
片段中的状态保存以类似的方式工作,但实际的状态保存需要一些额外的工作,但是有很多文章处理这个问题,所以你应该没有问题找出如何,原理保存 scrollY 和恢复它保持不变。