Skip to content

Instantly share code, notes, and snippets.

@FrantisekGazo
Last active November 10, 2024 22:57
Show Gist options
  • Save FrantisekGazo/a9cc4e18cee42199a287 to your computer and use it in GitHub Desktop.
Save FrantisekGazo/a9cc4e18cee42199a287 to your computer and use it in GitHub Desktop.
Retain & restore recycler view scroll position
package eu.f3rog.ui.custom;
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
/**
* Class {@link StatefulRecyclerView} extends {@link RecyclerView} and adds position management on configuration changes.
*
* @author FrantisekGazo
* @version 2016-03-15
*/
public final class StatefulRecyclerView
extends RecyclerView {
private static final String SAVED_SUPER_STATE = "super-state";
private static final String SAVED_LAYOUT_MANAGER = "layout-manager-state";
private Parcelable mLayoutManagerSavedState;
public StatefulRecyclerView(Context context) {
super(context);
}
public StatefulRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public StatefulRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
bundle.putParcelable(SAVED_SUPER_STATE, super.onSaveInstanceState());
bundle.putParcelable(SAVED_LAYOUT_MANAGER, this.getLayoutManager().onSaveInstanceState());
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
mLayoutManagerSavedState = bundle.getParcelable(SAVED_LAYOUT_MANAGER);
state = bundle.getParcelable(SAVED_SUPER_STATE);
}
super.onRestoreInstanceState(state);
}
/**
* Restores scroll position after configuration change.
* <p>
* <b>NOTE:</b> Must be called after adapter has been set.
*/
private void restorePosition() {
if (mLayoutManagerSavedState != null) {
this.getLayoutManager().onRestoreInstanceState(mLayoutManagerSavedState);
mLayoutManagerSavedState = null;
}
}
@Override
public void setAdapter(Adapter adapter) {
super.setAdapter(adapter);
restorePosition();
}
}
@chriskikoti
Copy link

Worked fine. Thanks

@chieuancucbo
Copy link

If you are looking for a solution, don't do like that, you will never know how to use the code.

Now do like this:
All below code you put in the activity (where you using the Recyclerview)

// save position:
RecyclerView rcv = findViewById(.....);
rcv.setAdapter(....);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
rcv.setLayoutManager(layoutManager);

rcv.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                pos = layoutManager.findFirstVisibleItemPosition();
               // everytime you scroll the list, new position will be saved in app's data storage:
                SharedPreferences preferences = getSharedPreferences("anyname", MODE_PRIVATE);
                SharedPreferences.Editor editor = preferences.edit();
                editor.putInt("KEY_LAST_POSITION", pos).apply();
            }
        });

// using position: 
SharedPreferences preferences = getSharedPreferences("anyname", MODE_PRIVATE);
int position = preferences.getInt("KEY_LAST_POSITION", 0); // 0 is the default value
rcv.scrollToPosition(position);

@MichalDanielDobrzanski
Copy link

MichalDanielDobrzanski commented Jan 18, 2022

@chieuancucbo you don't know your code. It is remembering an item position, not the exact scroll.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment