user3706687
user3706687

Reputation:

How to retain the scrolled position of a Recycler view on back press from another activity?

I saw many related questions about this topic, but none of them helped me. I am using a StaggeredGridLayout for my RecyclerView (showing cards). Every CardView opens a new activity, the problem I am facing is that on back press from that new activity, the RecyclerView scrolls back to the top. I want it to retain the previously scrolled position.

This what I use for now to set the layout :

rv.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
rv.setHasFixedSize(true);

Any proper working solution for a newbie?

EDIT :

   @Override
 protected void onResume() {
     super.onResume();
    if (listState != null) {
        rvlayout.onRestoreInstanceState(listState);
    }
      initializeData();

 }

Layout :

RecyclerView.LayoutManager rvlayout = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);

and initializeData :

 public void initializeData() {

    rv.setLayoutManager(rvlayout);
    rv.setHasFixedSize(true);
    persons.clear();

    c = db.rawQuery(SELECT_SQL, null);
    c.moveToFirst();

    if (!c.moveToFirst())
    return;


    while (!c.isLast()) {
        id = c.getString(0);
        names = c.getString(1);
        age = c.getString(2);
        persons.add(new Person(id,names,age));
        c.moveToNext();
    }

    adapter = new RVAdapter(persons);
    rv.setAdapter(adapter);

}

Upvotes: 3

Views: 9374

Answers (5)

Badr
Badr

Reputation: 2091

Try to add setRetainInstance(true) in your Oncreate fragment method like this:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);
}

The setRetainInstance(boolean retain) method Controls whether a fragment instance is retained across Activity re-creation (such as from a configuration change).

Upvotes: 0

David Rauca
David Rauca

Reputation: 1583

If you don't load the list again (when press back button) the recycler view scroll should be at the same position. Do you reload the list in onResume()?

UPDATE

I've just tried the solution that I mentioned in the comment below but with no results. I hope this code example will help you:

private int scrollPosition = 0;
private boolean shouldKeepScrollPosition = true;

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            if(shouldKeepScrollPosition) {
                MyFragment.this.scrollPosition += dy;
            }
        }
    });

Before reload data do this:

shouldKeepScrollPosition = false;

After reload data:

shouldKeepScrollPosition = true;
recyclerView.scrollBy(0, scrollPosition);

Upvotes: 1

JAAD
JAAD

Reputation: 12379

use
rv.smoothScrollToPosition(position); or
rv.scrollToPosition(position);

to maintain scroll position . when u open new activity save position in a variable , sharedpreference . and call rv.smoothScrollToPosition(position)or rv.scrollToPosition(position) in initializeData();

Upvotes: 0

capt.swag
capt.swag

Reputation: 10661

The proper way to do it is to save the state of RecyclerView scroll position and restore it while switching between Activities.

1. To save it, override onSaveInstanceState()

protected void onSaveInstanceState(Bundle state) {
    super.onSaveInstanceState(state);

    state.putParcelable(LIST_STATE_KEY, layoutManager.onSaveInstanceState());
}

2. To retrieve the data override onRestoreInstanceState()

protected void onRestoreInstanceState(Bundle state) {
    super.onRestoreInstanceState(state);

    Parcelable listState = state.getParcelable(LIST_STATE_KEY);
}

3. And finally update the LayoutManager in onResume() method

@Override
protected void onResume() {
    super.onResume();

    if (listState != null) {
        layoutManager.onRestoreInstanceState(listState);
    }
}

Upvotes: 8

Jagoan Neon
Jagoan Neon

Reputation: 1128

No idea why that's happening... but you can probably make use of startActivityForResult. Make sure you save the clicked position in the list before calling the method.

Override onActivityResult in that Activity that has your grid layout and call mRecyclerView.scrollToPosition(mLastScrolledPosition) there.

Upvotes: 0

Related Questions