Как сохранить положение прокрутки RecyclerView с помощью RecyclerView.State?

У меня вопрос о Android RecyclerView.State .

Я использую RecyclerView, как я могу использовать и привязывать его к RecyclerView.State?

Моя цель – сохранить положение прокрутки RecyclerView .

Solutions Collecting From Web of "Как сохранить положение прокрутки RecyclerView с помощью RecyclerView.State?"

Как вы планируете сохранить последнюю сохраненную позицию с помощью 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, он поставляется с предварительно созданным сохранением api linearLayoutManagerInstance.onSaveInstanceState () и восстанавливает api linearLayoutManagerInstance.onRestoreInstanceState (…)

При этом вы можете сохранить возвращенную аргументацию в ваш 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()); } 

Изменить: вы также можете использовать один и тот же apis с GridLayoutManager, так как это подкласс LinearLayoutManager. Спасибо @wegsehen для предложения.

магазин

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

восстановить

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

И если это не сработает, попробуйте

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

Положить магазин в onPause и восстановить в onResume

I Установите переменные в onCreate (), сохраните положение прокрутки в 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, когда вы переходите от моей активности в списке, а затем нажмите кнопку «Назад», чтобы вернуться назад. Многие из решений, предоставленных для этой проблемы, были либо намного сложнее, чем необходимо, либо не работали для моей конфигурации, поэтому я решил поделиться своим решением.

Сначала сохраните состояние экземпляра в 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) (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(); } 

Почему я использую OnSaveInstanceState() в onPause() означает, что будет переключен на другую активность onPause. Он сохранит эту позицию прокрутки и восстановит позицию, когда мы вернемся из другого действия.