編集:まったく同じ見かけの位置を復元するには、それをまったく同じように見せるために、少し違うことをする必要があります(正確な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に保存されます。
この変数をバンドルに保存し、状態の復元で別の変数に復元します。これをmStateScrollYと呼びます。
状態の復元後、RecyclerViewがすべてのデータをリセットした後、次のようにしてスクロールをリセットします。
mRecyclerView.scrollBy(0, mStateScrollY);
それでおしまい。
スクロールを別の変数に復元することに注意してください。OnScrollListenerは.scrollBy()で呼び出され、その後mScrollYをmStateScrollYに格納されている値に設定するため、これは重要です。これを行わないと、mScrollYのスクロール値が2倍になります(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);
}
フラグメントでの状態保存は同様の方法で機能しますが、実際の状態保存には少し余分な作業が必要ですが、それを扱う記事はたくさんあるので、スクロールを保存する原理を見つけるのに問題はないはずですY復元は同じままです。