Как предотвратить потерю состояния пользовательских видов при изменении ориентации экрана

Я успешно реализовал onRetainNonConfigurationInstance () для моей основной деятельности , чтобы сохранить и восстановить некоторые критические компоненты при изменении ориентации экрана.

Но, похоже, мои пользовательские виды воссоздаются с нуля, когда меняется ориентация. Это имеет смысл, хотя в моем случае это неудобно, поскольку рассматриваемый пользовательский вид представляет собой график X / Y, а точки на графике сохраняются в пользовательском представлении.

Есть ли хитрый способ реализовать что-то похожее на onRetainNonConfigurationInstance () для настраиваемого представления, или мне нужно просто реализовать методы в настраиваемом представлении, которые позволяют мне получать и устанавливать его «состояние» ?

243
задан JJD 24 October 2014 в 03:27
поделиться

1 ответ

Вы делаете это, реализуя 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 и SavedState View. Вы должны выполнять всю работу по чтению и записи в и из Parcel в классе SavedState. Затем ваш класс View может выполнить работу по извлечению членов состояния и выполнить работу, необходимую для возврата класса в допустимое состояние.

Примечания: View#onSavedInstanceState и View#onRestoreInstanceState вызываются автоматически, если View#getId возвращает значение >= 0. Это происходит, когда вы дайте ему идентификатор в xml или вызовите setId вручную. В противном случае вам нужно вызвать View#onSaveInstanceState и записать Parcelable, возвращенный посылке, которую вы получаете в Activity#onSaveInstanceState, чтобы сохранить состояние, а затем прочитать его и передать View #onRestoreInstanceState из Activity#onRestoreInstanceState.

Другим простым примером этого является CompoundButton

408
ответ дан 23 November 2019 в 03:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: