小编典典

如何防止自定义视图在屏幕方向更改时丢失状态

all

我已经成功地onRetainNonConfigurationInstance()为我的主实现了Activity跨屏幕方向更改保存和恢复某些关键组件。

但似乎,当方向改变时,我的自定义视图正在从头开始重新创建。这是有道理的,尽管在我的情况下这很不方便,因为有问题的自定义视图是 X/Y
图,并且绘制的点存储在自定义视图中。

有没有一种巧妙的方法来实现类似于onRetainNonConfigurationInstance()自定义视图的东西,还是我只需要在自定义视图中实现允许我获取和设置其“状态”的方法?


阅读 72

收藏
2022-05-12

共1个答案

小编典典

您可以通过实现和扩展类来做到View#onSaveInstanceStateView#onRestoreInstanceState一点View.BaseSavedState

public class CustomView extends View {

  private int stateToSave;

  ...

  @Override
  public Parcelable onSaveInstanceState() {
    //begin boilerplate code that allows parent classes to save state
    Parcelable superState = super.onSaveInstanceState();

    SavedState ss = new SavedState(superState);
    //end

    ss.stateToSave = this.stateToSave;

    return ss;
  }

  @Override
  public void onRestoreInstanceState(Parcelable state) {
    //begin boilerplate code so parent classes can restore state
    if(!(state instanceof SavedState)) {
      super.onRestoreInstanceState(state);
      return;
    }

    SavedState ss = (SavedState)state;
    super.onRestoreInstanceState(ss.getSuperState());
    //end

    this.stateToSave = ss.stateToSave;
  }

  static class SavedState extends BaseSavedState {
    int stateToSave;

    SavedState(Parcelable superState) {
      super(superState);
    }

    private SavedState(Parcel in) {
      super(in);
      this.stateToSave = in.readInt();
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
      super.writeToParcel(out, flags);
      out.writeInt(this.stateToSave);
    }

    //required field that makes Parcelables from a Parcel
    public static final Parcelable.Creator<SavedState> CREATOR =
        new Parcelable.Creator<SavedState>() {
          public SavedState createFromParcel(Parcel in) {
            return new SavedState(in);
          }
          public SavedState[] newArray(int size) {
            return new SavedState[size];
          }
    };
  }
}

工作在 View 和 View 的 SavedState
类之间进行拆分。Parcel你应该在SavedState课堂上完成所有的阅读和写作工作。然后,您的 View
类可以完成提取状态成员的工作,并完成使类恢复到有效状态所需的工作。

注意:如果返回值 >= 0 View#onSavedInstanceState,则会自动为您调用。当您在 xml 中给它一个 id
或手动调用时,就会发生这种情况。否则,您必须调用并写入返回到您进入的包裹的 Parcelable以保存状态,然后读取它并将其传递给from
View#onRestoreInstanceState``View#getId``setId``View#onSaveInstanceState``Activity#onSaveInstanceState``View#onRestoreInstanceState``Activity#onRestoreInstanceState

另一个简单的例子是CompoundButton

2022-05-12