264

画面の向きが変わっても、特定の重要なコンポーネントを保存および復元するためonRetainNonConfigurationInstance()のメインの実装に成功しました。Activity

しかし、向きが変わると、カスタム ビューが最初から再作成されているようです。これは理にかなっていますが、問題のカスタム ビューは X/Y プロットであり、プロットされた点はカスタム ビューに格納されるため、私の場合は不便です。

カスタムビューに似たものを実装する巧妙な方法はありますonRetainNonConfigurationInstance()か、それともカスタムビューに「状態」を取得および設定できるメソッドを実装する必要がありますか?

4

10 に答える 10

476

これはもっとシンプルなバージョンだと思います。Bundleを実装する組み込み型です。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);
  }
}
于 2011-11-14T20:41:20.617 に答える
423

これを行うには、クラスを実装View#onSaveInstanceStateおよびView#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 クラスは状態メンバーを抽出し、クラスを有効な状態に戻すために必要な作業を実行できます。

注: View#onSavedInstanceStateandは、値 >= 0 を返すView#onRestoreInstanceState場合に自動的に呼び出されます。これは、xml で ID を指定するか、手動で呼び出すと発生します。それ以外の場合は、取得したパーセルに返された Parcelableを呼び出して書き込み、状態を保存し、その後それを読み取ってfromに渡す必要があります。View#getIdsetIdView#onSaveInstanceStateActivity#onSaveInstanceStateView#onRestoreInstanceStateActivity#onRestoreInstanceState

これの別の簡単な例は、CompoundButton

于 2010-08-22T19:02:58.423 に答える
18

上記の 2 つの方法を組み合わせて使用​​する別のバリ​​アントを次に示します。の速度と正確性をParcelablea の単純さと組み合わせるBundle:

@Override
public Parcelable onSaveInstanceState() {
    Bundle bundle = new Bundle();
    // The vars you want to save - in this instance a string and a boolean
    String someString = "something";
    boolean someBoolean = true;
    State state = new State(super.onSaveInstanceState(), someString, someBoolean);
    bundle.putParcelable(State.STATE, state);
    return bundle;
}

@Override
public void onRestoreInstanceState(Parcelable state) {
    if (state instanceof Bundle) {
        Bundle bundle = (Bundle) state;
        State customViewState = (State) bundle.getParcelable(State.STATE);
        // The vars you saved - do whatever you want with them
        String someString = customViewState.getText();
        boolean someBoolean = customViewState.isSomethingShowing());
        super.onRestoreInstanceState(customViewState.getSuperState());
        return;
    }
    // Stops a bug with the wrong state being passed to the super
    super.onRestoreInstanceState(BaseSavedState.EMPTY_STATE); 
}

protected static class State extends BaseSavedState {
    protected static final String STATE = "YourCustomView.STATE";

    private final String someText;
    private final boolean somethingShowing;

    public State(Parcelable superState, String someText, boolean somethingShowing) {
        super(superState);
        this.someText = someText;
        this.somethingShowing = somethingShowing;
    }

    public String getText(){
        return this.someText;
    }

    public boolean isSomethingShowing(){
        return this.somethingShowing;
    }
}
于 2012-05-11T14:27:36.663 に答える