Как сохранить позицию прокрутки RecyclerView с помощью RecyclerView.Государство?
У меня есть вопрос о Android RecyclerView.Государство.
Я использую RecyclerView, как я могу использовать и связать его с RecyclerView.Государство?
моя цель -сохранить позицию прокрутки RecyclerView.
10 ответов:
как вы планируете сохранить последнюю сохраненную позицию с
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, он поставляется с предварительно построенным save api linearLayoutManagerInstance.данные метода onsaveinstance() и восстановить api linearLayoutManagerInstance.onRestoreInstanceState(...)
С этим вы можете сохранить возвращенный parcelable в свой штат. например,
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()); }
Edit: вы также можете использовать те же API с GridLayoutManager, так как это подкласс LinearLayoutManager. Спасибо @wegsehen за предложение.
Edit: помните, если вы также загружаете данные в фоновом потоке, вам нужно будет вызвать onRestoreInstanceState в вашем методе onPostExecute/onLoadFinished для восстановления позиции при изменении ориентации, например
@Override protected void onPostExecute(ArrayList<Movie> movies) { mLoadingIndicator.setVisibility(View.INVISIBLE); if (movies != null) { showMoviePosterDataView(); mDataAdapter.setMovies(movies); mRecyclerView.getLayoutManager().onRestoreInstanceState(mSavedRecyclerLayoutState); } else { showErrorMessage(); } }
магазине
lastFirstVisiblePosition = ((LinearLayoutManager)rv.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
восстановить
((LinearLayoutManager) rv.getLayoutManager()).scrollToPosition(lastFirstVisiblePosition);
и если это не сработает, попробуй
((LinearLayoutManager) rv.getLayoutManager()).scrollToPositionWithOffset(lastFirstVisiblePosition,0)
положить магазин в
onPause()
и восстановить вonResume()
Я задать переменные в методе 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/
вот как я восстанавливаю позицию RecyclerView с помощью GridLayoutManager после поворота, когда вам нужно перезагрузить данные из интернета с помощью AsyncTaskLoader.
сделайте глобальную переменную Parcelable и GridLayoutManager и статическую конечную строку:
private Parcelable savedRecyclerLayoutState; private GridLayoutManager mGridLayoutManager; private static final String BUNDLE_RECYCLER_LAYOUT = "recycler_layout";
сохранить состояние gridLayoutManager в onSaveInstance ()
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelable(BUNDLE_RECYCLER_LAYOUT, mGridLayoutManager.onSaveInstanceState()); }
восстановить в onRestoreInstanceState
@Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); //restore recycler view at same position if (savedInstanceState != null) { savedRecyclerLayoutState = savedInstanceState.getParcelable(BUNDLE_RECYCLER_LAYOUT); } }
затем, когда загрузчик извлекает данные из интернета, вы восстанавливаете recyclerview положение в onLoadFinished()
if(savedRecyclerLayoutState!=null){ mGridLayoutManager.onRestoreInstanceState(savedRecyclerLayoutState); }
..конечно, вы должны создать экземпляр gridLayoutManager внутри onCreate. Ура
для меня проблема заключалась в том, что я настраивал новый layoutmanager каждый раз, когда я менял свой адаптер, теряя позицию прокрутки que на recyclerView.
вот мой подход, чтобы сохранить их и поддерживать состояние recyclerview в фрагменте. Во-первых, добавьте изменения конфигурации в родительской деятельности, как показано ниже кода.
android:configChanges="orientation|screenSize"
затем в вашем фрагменте объявите эти экземпляры метода
private Bundle mBundleRecyclerViewState; private Parcelable mListState = null; private LinearLayoutManager mLinearLayoutManager;
добавить ниже код в вашем @ onPause метод
@Override public void onPause() { super.onPause(); //This used to store the state of recycler view mBundleRecyclerViewState = new Bundle(); mListState =mTrailersRecyclerView.getLayoutManager().onSaveInstanceState(); mBundleRecyclerViewState.putParcelable(getResources().getString(R.string.recycler_scroll_position_key), mListState); }
добавить onConfigartionChanged метод, как показано ниже.
@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); //When orientation is changed then grid column count is also changed so get every time Log.e(TAG, "onConfigurationChanged: " ); if (mBundleRecyclerViewState != null) { new Handler().postDelayed(new Runnable() { @Override public void run() { mListState = mBundleRecyclerViewState.getParcelable(getResources().getString(R.string.recycler_scroll_position_key)); mTrailersRecyclerView.getLayoutManager().onRestoreInstanceState(mListState); } }, 50); } mTrailersRecyclerView.setLayoutManager(mLinearLayoutManager); }
этот подход позволит решить вашу проблему. если у вас есть diffrent layout manager, то просто замените верхний менеджер компоновки.
активности.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()
inonPause()
означает, что при переключении на другую активность onPause будет called.It сохранит эту позицию прокрутки и восстановит позицию, когда мы вернемся из другой деятельности.