1

My ListView (StickyListHeadersListView) does not save the exact scroll position. I referenced this:

Maintain/Save/Restore scroll position when returning to a ListView

When a user taps on an item in the list, I use SharedPreferences to save the "index" and "top" before the app transitions to an activity. When I press back on the activity to go back to the fragment with the ListView, the list goes to the top of the first visible list item from when it left, but not the exact position (i.e. if the first visible item is cut off halfway, it should be cut off halfway when returning to the fragment).

In other words, the offset is not saving. Like I said, it can save the first visible position, but the exact scroll is not being saved.

    mAdapter = new PeopleAdapter(getActivity(), null);
    mList = (StickyListHeadersListView) rootView.findViewById(R.id.stickyList);
    mList.setAdapter(mAdapter);
    mList.setAreHeadersSticky(true);
    mList.setDividerHeight(0);
    mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Cursor cursor = mAdapter.getCursor();
            if (cursor != null && cursor.moveToPosition(position)) {
                MainActivity.setIndex(mList.getFirstVisiblePosition());
                View v = mList.getListChildAt(0);
                int top = (v == null) ? 0 : (v.getTop() - mList.getPaddingTop());
                MainActivity.setTop(top);
                Intent intent = new Intent(getActivity(), ContactDetailActivity.class);
                startActivity(intent);
        }
    });

After the cursor is done loading, I'm calling

    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        android.util.Log.i(TAG, "Cursor loaded. (" + data.getCount() + " rows)");
        mList.setSelectionFromTop(MainActivity.getIndex(), MainActivity.getTop());
        mAdapter.changeCursor(data);
        mAdapter.notifyDataSetChanged();
}
Community
  • 1
  • 1
Michael McKenna
  • 811
  • 1
  • 11
  • 24

1 Answers1

0

It's possible to use savedInstanceState to save the exact scroll of the ListView however, this is destroyed along with the activity under many circumstances and we can't easily persist the savedInstanceState as we can only really convert it into a Parcelable object, which isn't designed to be persisted. Even when trying to get the savedInstanceState from the ListView we have a few problems. null is often given back to us as the Android documentation specifies happens when there's "nothing interesting to save". Well, in this scenario, the scroll is pretty interesting! Sadly, Android isn't always going to give us this though, which brings a lot of problems...

In fact, I looked this up a bit more and noticed the Android documentation says "This state should only contain information that is not persistent or can not be reconstructed later. For example, you will never store your current position on screen because that will be computed again when a new instance of the view is placed in its view hierarchy.", so this is not the way to go.

Of course, we can still use the method you're using however, it will never be exact across all devices. For a general app, I would recommend just persisting the index of the list item and starting the user back at the top.

I don't believe there are any other methods we can use to access the scroll position, apart from getting the details from the ListView itself. Therefore, we can only use what we're given.

You could be super crazy mind, and try out putting a ListView in a ScrollView (Or some other containers would work too), where we can then use methods like getScrollY() and setScrollY() but this relies on there always being the same number of list items and all list items staying the same size.

Michael McKenna
  • 811
  • 1
  • 11
  • 24