How to save scroll position of RecyclerView in And

2019-01-09 06:08发布

问题:

I have Recycler view which lays inside of SwipeRefreshLayout. Also, have ability to open each item in another activity. After returning back to Recycler I need scroll to chosen item, or to previous Y. How to do that?

Yes, I googled, found articles in StackOverFlow about saving instance of layout manager, like this one: RecyclerView store / restore state between activities. But, it doesn't help me.

UPDATE

Right now I have this kind of resolving problem, but, of course, it also doesn't work.

private int scrollPosition;

...//onViewCreated - it is fragment
recyclerView.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(llm);
data = new ArrayList<>();
adapter.setData(getActivity(), data);
recyclerView.setAdapter(adapter);
...

@Override
public void onResume() {
    super.onResume();
    recyclerView.setScrollY(scrollPosition);
}

@Override
public void onPause() {
    super.onPause();
    scrollPosition = recyclerView.getScrollY();
}

Yes, I have tried scrollTo(int, int) - doen't work.

Now I tried just scroll, for example, to Y = 100, but it doesn't scrolling at all.

回答1:

Save the current state of recycle view position @onPause:

    positionIndex= llManager.findFirstVisibleItemPosition();
    View startView = rv.getChildAt(0);
    topView = (startView == null) ? 0 : (startView.getTop() - rv.getPaddingTop());

Restore the scroll position @onResume:

    if (positionIndex!= -1) {
        llManager.scrollToPositionWithOffset(positionIndex, topView);
    }

or another way can be @onPause:

long currentVisiblePosition = 0;
currentVisiblePosition = ((LinearLayoutManager)rv.getLayoutManager()).findFirstCompletelyVisibleItemPosition();

restore @onResume:

((LinearLayoutManager) rv.getLayoutManager()).scrollToPosition(currentVisiblePosition);
currentVisiblePosition = 0;


回答2:

A lot of these answers seem to be over complicating it.

The LayoutManager supports onRestoreInstanceState out of the box so there is no need to save scroll positions etc. The built in method already saves pixel perfect positions.

example fragment code (null checking etc removed for clarity):

private Parcelable listState;
private RecyclerView list;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    listState=savedInstanceState.getParcelable("ListState");

}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.putParcelable("ListState", list.getLayoutManager().onSaveInstanceState());

}

then just call

list.getLayoutManager().onRestoreInstanceState(listState);

once your data has been reattached to your RecyclerView



回答3:

User your recycler view linearlayoutmanager for getting scroll position

int position = 0;
if (linearLayoutManager != null) {
   scrollPosition = inearLayoutManager.findFirstVisibleItemPosition();
}

and when restoring use following code

if (linearLayoutManager != null) {
  cardRecyclerView.scrollToPosition(mScrollPosition);
}

Hope this helps you



回答4:

You can use scrollToPosition or smoothScrollToPosition to scroll to any item position in RecyclerView.

If you want to scroll to item position in adapter, then you would have to use adapter's scrollToPosition or smoothScrollToPosition.



回答5:

to save position to Preferences, add this to your onStop()

 int currentVisiblePosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
 getPreferences(MODE_PRIVATE).edit().putInt("listPosition", currentVisiblePosition).apply();

then restore position like this

 if (getItemCount() == 0) {
     int savedListPosition = getPreferences(MODE_PRIVATE).getInt("listPosition", 0);
     recyclerView.getLayoutManager().scrollToPosition(savedListPosition); }

this last code should be added inside an event of the Adapter (not sure witch event but in my case was onEvent() - com.google.firebase.firestore.EventListener)