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

后端 未结 20 1684
無奈伤痛
無奈伤痛 2020-11-21 21:30

I have a long ListView that the user can scroll around before returning to the previous screen. When the user opens this ListView again, I want the

20条回答
  •  醉酒成梦
    2020-11-21 22:05

    Neither of the solutions offered here seemed to work for me. In my case, I have a ListView in a Fragment which I'm replacing in a FragmentTransaction, so a new Fragment instance is created each time the fragment is shown, which means that the ListView state can not be stored as a member of the Fragment.

    Instead, I ended up storing the state in my custom Application class. The code below should give you an idea how this works:

    public class MyApplication extends Application {
        public static HashMap parcelableCache = new HashMap<>();
    
    
        /* ... code omitted for brevity ... */
    }
    

     

    public class MyFragment extends Fragment{
        private ListView mListView = null;
        private MyAdapter mAdapter = null;
    
    
        @Override
        public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
    
            mAdapter = new MyAdapter(getActivity(), null, 0);
            mListView = ((ListView) view.findViewById(R.id.myListView));
    
            Parcelable listViewState = MyApplication.parcelableCache.get("my_listview_state");
            if( listViewState != null )
                mListView.onRestoreInstanceState(listViewState);
        }
    
    
        @Override
        public void onPause() {
            MyApplication.parcelableCache.put("my_listview_state", mListView.onSaveInstanceState());
            super.onPause();
        }
    
        /* ... code omitted for brevity ... */
    
    }
    

    The basic idea is that you store the state outside the fragment instance. If you don't like the idea of having a static field in your application class, I guess you could do it by implementing a fragment interface and storing the state in your activity.

    Another solution would be to store it in SharedPreferences, but it gets a bit more complicated, and you would need to make sure you clear it on application launch unless you want the state to be persisted across app launches.

     

    Also, to avoid the "scroll position not saved when first item is visible", you can display a dummy first item with 0px height. This can be achieved by overriding getView() in your adapter, like this:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if( position == 0 ) {
            View zeroHeightView = new View(parent.getContext());
            zeroHeightView.setLayoutParams(new ViewGroup.LayoutParams(0, 0));
            return zeroHeightView;
        }
        else
            return super.getView(position, convertView, parent);
    }
    

提交回复
热议问题