How to prevent custom views from losing state across screen orientation changes

后端 未结 9 896
时光说笑
时光说笑 2020-11-22 10:11

I\'ve successfully implemented onRetainNonConfigurationInstance() for my main Activity to save and restore certain critical components across screen orientation

相关标签:
9条回答
  • 2020-11-22 10:59

    To augment other answers - if you have multiple custom compound views with the same ID and they are all being restored with the state of the last view on a configuration change, all you need to do is tell the view to only dispatch save/restore events to itself by overriding a couple of methods.

    class MyCompoundView : ViewGroup {
    
        ...
    
        override fun dispatchSaveInstanceState(container: SparseArray<Parcelable>) {
            dispatchFreezeSelfOnly(container)
        }
    
        override fun dispatchRestoreInstanceState(container: SparseArray<Parcelable>) {
            dispatchThawSelfOnly(container)
        }
    }
    

    For an explanation of what is happening and why this works, see this blog post. Basically your compound view's children's view IDs are shared by each compound view and state restoration gets confused. By only dispatching state for the compound view itself, we prevent their children from getting mixed messages from other compound views.

    0 讨论(0)
  • 2020-11-22 11:01

    I had the problem that onRestoreInstanceState restored all my custom views with the state of the last view. I solved it by adding these two methods to my custom view:

    @Override
    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
        dispatchFreezeSelfOnly(container);
    }
    
    @Override
    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
        dispatchThawSelfOnly(container);
    }
    
    0 讨论(0)
  • 2020-11-22 11:02

    I think this is a much simpler version. Bundle is a built-in type which implements Parcelable

    public class CustomView extends View
    {
      private int stuff; // stuff
    
      @Override
      public Parcelable onSaveInstanceState()
      {
        Bundle bundle = new Bundle();
        bundle.putParcelable("superState", super.onSaveInstanceState());
        bundle.putInt("stuff", this.stuff); // ... save stuff 
        return bundle;
      }
    
      @Override
      public void onRestoreInstanceState(Parcelable state)
      {
        if (state instanceof Bundle) // implicit null check
        {
          Bundle bundle = (Bundle) state;
          this.stuff = bundle.getInt("stuff"); // ... load stuff
          state = bundle.getParcelable("superState");
        }
        super.onRestoreInstanceState(state);
      }
    }
    
    0 讨论(0)
提交回复
热议问题