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

后端 未结 20 2063
無奈伤痛
無奈伤痛 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:10

    I'm using FirebaseListAdapter and couldn't get any of the solutions to work. I ended up doing this. I'm guessing there are more elegant ways but this is a complete and working solution.

    Before onCreate:

    private int reset;
    private int top;
    private int index;
    

    Inside of the FirebaseListAdapter:

    @Override
    public void onDataChanged() {
         super.onDataChanged();
    
         // Only do this on first change, when starting
         // activity or coming back to it.
         if(reset == 0) {
              mListView.setSelectionFromTop(index, top);
              reset++;
         }
    
     }
    

    onStart:

    @Override
    protected void onStart() {
        super.onStart();
        if(adapter != null) {
            adapter.startListening();
            index = 0;
            top = 0;
            // Get position from SharedPrefs
            SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
            top = sharedPref.getInt("TOP_POSITION", 0);
            index = sharedPref.getInt("INDEX_POSITION", 0);
            // Set reset to 0 to allow change to last position
            reset = 0;
        }
    }
    

    onStop:

    @Override
    protected void onStop() {
        super.onStop();
        if(adapter != null) {
            adapter.stopListening();
            // Set position
            index = mListView.getFirstVisiblePosition();
            View v = mListView.getChildAt(0);
            top = (v == null) ? 0 : (v.getTop() - mListView.getPaddingTop());
            // Save position to SharedPrefs
            SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
            sharedPref.edit().putInt("TOP_POSITION" + "", top).apply();
            sharedPref.edit().putInt("INDEX_POSITION" + "", index).apply();
        }
    }
    

    Since I also had to solve this for FirebaseRecyclerAdapter I'm posting the solution here for that too:

    Before onCreate:

    private int reset;
    private int top;
    private int index;
    

    Inside of the FirebaseRecyclerAdapter:

    @Override
    public void onDataChanged() {
        // Only do this on first change, when starting
        // activity or coming back to it.
        if(reset == 0) {
            linearLayoutManager.scrollToPositionWithOffset(index, top);
            reset++;
        }
    }
    

    onStart:

    @Override
    protected void onStart() {
        super.onStart();
        if(adapter != null) {
            adapter.startListening();
            index = 0;
            top = 0;
            // Get position from SharedPrefs
            SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
            top = sharedPref.getInt("TOP_POSITION", 0);
            index = sharedPref.getInt("INDEX_POSITION", 0);
            // Set reset to 0 to allow change to last position
            reset = 0;
        }
    }
    

    onStop:

    @Override
    protected void onStop() {
        super.onStop();
        if(adapter != null) {
            adapter.stopListening();
            // Set position
            index = linearLayoutManager.findFirstVisibleItemPosition();
            View v = linearLayoutManager.getChildAt(0);
            top = (v == null) ? 0 : (v.getTop() - linearLayoutManager.getPaddingTop());
            // Save position to SharedPrefs
            SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
            sharedPref.edit().putInt("TOP_POSITION" + "", top).apply();
            sharedPref.edit().putInt("INDEX_POSITION" + "", index).apply();
        }
    }
    

提交回复
热议问题