如何使用RecyclerView.State保存RecyclerView的滚动位置?

我有一个关于Android的RecyclerView.State的问题。

我正在使用一个RecyclerView,我怎么能使用和RecyclerView.State绑定它?

我的目的是保存RecyclerView的滚动位置

你打算如何保存最后保存的位置与RecyclerView.State

你总是可以依靠好的保存状态。 扩展RecyclerView并覆盖onSaveInstanceState()和onRestoreInstanceState()

 @Override protected Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); LayoutManager layoutManager = getLayoutManager(); if(layoutManager != null && layoutManager instanceof LinearLayoutManager){ mScrollPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition(); } SavedState newState = new SavedState(superState); newState.mScrollPosition = mScrollPosition; return newState; } @Override protected void onRestoreInstanceState(Parcelable state) { super.onRestoreInstanceState(state); if(state != null && state instanceof SavedState){ mScrollPosition = ((SavedState) state).mScrollPosition; LayoutManager layoutManager = getLayoutManager(); if(layoutManager != null){ int count = layoutManager.getChildCount(); if(mScrollPosition != RecyclerView.NO_POSITION && mScrollPosition < count){ layoutManager.scrollToPosition(mScrollPosition); } } } } static class SavedState extends android.view.View.BaseSavedState { public int mScrollPosition; SavedState(Parcel in) { super(in); mScrollPosition = in.readInt(); } SavedState(Parcelable superState) { super(superState); } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeInt(mScrollPosition); } public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { @Override public SavedState createFromParcel(Parcel in) { return new SavedState(in); } @Override public SavedState[] newArray(int size) { return new SavedState[size]; } }; } 

如果你正在使用LinearLayoutManager,它带有预build的保存API linearLayoutManagerInstance.onSaveInstanceState()和恢复api linearLayoutManagerInstance.onRestoreInstanceState(…)

有了这个,你可以保存返回的parcelable到你的outState。 例如,

 outState.putParcelable("KeyForLayoutManagerState", linearLayoutManagerInstance.onSaveInstanceState()); 

,并以您保存的状态恢复恢复位置。 例如,

 Parcelable state = savedInstanceState.getParcelable("KeyForLayoutManagerState"); linearLayoutManagerInstance.onRestoreInstanceState(state); 

总结一下,你的最终代码看起来像这样

 private static final String BUNDLE_RECYCLER_LAYOUT = "classname.recycler.layout"; /** * This is a method for Fragment. * You can do the same in onCreate or onRestoreInstanceState */ @Override public void onViewStateRestored(@Nullable Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); if(savedInstanceState != null) { Parcelable savedRecyclerLayoutState = savedInstanceState.getParcelable(BUNDLE_RECYCLER_LAYOUT); recyclerView.getLayoutManager().onRestoreInstanceState(savedRecyclerLayoutState); } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelable(BUNDLE_RECYCLER_LAYOUT, recyclerView.getLayoutManager().onSaveInstanceState()); } 

编辑:你也可以使用与GridLayoutManager相同的API,因为它是LinearLayoutManager的子类。 感谢@wegsehen的build议。

商店

 lastFirstVisiblePosition = ((LinearLayoutManager)rv.getLayoutManager()).findFirstCompletelyVisibleItemPosition(); 

恢复

 ((LinearLayoutManager) rv.getLayoutManager()).scrollToPosition(lastFirstVisiblePosition); 

如果这不起作用,请尝试

 ((LinearLayoutManager) rv.getLayoutManager()).scrollToPositionWithOffset(lastFirstVisiblePosition,0) 

将商店放在onPause并在onResume中恢复

我在onCreate()中设置variables,在onPause()中保存滚动位置并在onResume()中设置滚动位置

 public static int index = -1; public static int top = -1; LinearLayoutManager mLayoutManager; @Override public void onCreate(Bundle savedInstanceState) { //Set Variables super.onCreate(savedInstanceState); cRecyclerView = ( RecyclerView )findViewById(R.id.conv_recycler); mLayoutManager = new LinearLayoutManager(this); cRecyclerView.setHasFixedSize(true); cRecyclerView.setLayoutManager(mLayoutManager); } @Override public void onPause() { super.onPause(); //read current recyclerview position index = mLayoutManager.findFirstVisibleItemPosition(); View v = cRecyclerView.getChildAt(0); top = (v == null) ? 0 : (v.getTop() - cRecyclerView.getPaddingTop()); } @Override public void onResume() { super.onResume(); //set recyclerview position if(index != -1) { mLayoutManager.scrollToPositionWithOffset( index, top); } } 

我想要在离开我的列表活动时再保存Recycler View的滚动位置,然后单击后退button导航回来。 为这个问题提供的许多解决scheme要么比需要更复杂,要么不适合我的configuration,所以我想我会分享我的解决scheme。

首先保存你的实例状态在onPause中,正如许多人所显示的那样。 我认为值得强调的是这个版本的onSaveInstanceState是RecyclerView.LayoutManager类的一个方法。

 private LinearLayoutManager mLayoutManager; Parcelable state; @Override public void onPause() { super.onPause(); state = mLayoutManager.onSaveInstanceState(); } 

让它正常工作的关键是确保在连接适配器之后调用onRestoreInstanceState,正如其他线程中指出的那样。 然而,实际的方法调用比许多人指出的要简单得多。

 private void someMethod() { mVenueRecyclerView.setAdapter(mVenueAdapter); mLayoutManager.onRestoreInstanceState(state); } 

你不必自己保存和恢复状态。 如果你在xml和recyclerView.setSaveEnabled(true)中设置了唯一的ID(默认情况下为true),系统会自动执行此操作。 这里是更多关于这个: http : //trickyandroid.com/saving-android-view-state-correctly/

Activity.java:

 public RecyclerView.LayoutManager mLayoutManager; Parcelable state; mLayoutManager = new LinearLayoutManager(this); // Inside `onCreate()` lifecycle method, put the below code : if(state != null) { mLayoutManager.onRestoreInstanceState(state); } @Override protected void onResume() { super.onResume(); if (state != null) { mLayoutManager.onRestoreInstanceState(state); } } @Override protected void onPause() { super.onPause(); state = mLayoutManager.onSaveInstanceState(); } 

为什么我在onPause()使用OnSaveInstanceState()意味着,切换到另一个activity onPause会被调用。它将保存该滚动位置,并恢复从其他活动回来的位置。