Die Antworten hier sind bereits großartig, funktionieren aber nicht unbedingt für benutzerdefinierte ViewGroups. Damit alle benutzerdefinierten Ansichten ihren Status beibehalten, müssen Sie onSaveInstanceState()
und onRestoreInstanceState(Parcelable state)
in jeder Klasse überschreiben . Sie müssen auch sicherstellen, dass alle eindeutige IDs haben, unabhängig davon, ob sie aus XML aufgeblasen oder programmgesteuert hinzugefügt wurden.
Was ich mir ausgedacht habe, war bemerkenswert ähnlich wie die Antwort von Kobor42, aber der Fehler blieb bestehen, weil ich die Ansichten programmgesteuert zu einer benutzerdefinierten ViewGroup hinzufügte und keine eindeutigen IDs zuwies.
Der von mato freigegebene Link funktioniert, bedeutet jedoch, dass keine der einzelnen Ansichten ihren eigenen Status verwaltet. Der gesamte Status wird in den ViewGroup-Methoden gespeichert.
Das Problem ist, dass beim Hinzufügen mehrerer dieser ViewGroups zu einem Layout die IDs ihrer Elemente aus der XML nicht mehr eindeutig sind (sofern sie in XML definiert sind). Zur Laufzeit können Sie die statische Methode aufrufen View.generateViewId()
, um eine eindeutige ID für eine Ansicht abzurufen. Dies ist nur über API 17 verfügbar.
Hier ist mein Code aus der ViewGroup (er ist abstrakt und mOriginalValue ist eine Typvariable):
public abstract class DetailRow<E> extends LinearLayout {
private static final String SUPER_INSTANCE_STATE = "saved_instance_state_parcelable";
private static final String STATE_VIEW_IDS = "state_view_ids";
private static final String STATE_ORIGINAL_VALUE = "state_original_value";
private E mOriginalValue;
private int[] mViewIds;
// ...
@Override
protected Parcelable onSaveInstanceState() {
// Create a bundle to put super parcelable in
Bundle bundle = new Bundle();
bundle.putParcelable(SUPER_INSTANCE_STATE, super.onSaveInstanceState());
// Use abstract method to put mOriginalValue in the bundle;
putValueInTheBundle(mOriginalValue, bundle, STATE_ORIGINAL_VALUE);
// Store mViewIds in the bundle - initialize if necessary.
if (mViewIds == null) {
// We need as many ids as child views
mViewIds = new int[getChildCount()];
for (int i = 0; i < mViewIds.length; i++) {
// generate a unique id for each view
mViewIds[i] = View.generateViewId();
// assign the id to the view at the same index
getChildAt(i).setId(mViewIds[i]);
}
}
bundle.putIntArray(STATE_VIEW_IDS, mViewIds);
// return the bundle
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
// We know state is a Bundle:
Bundle bundle = (Bundle) state;
// Get mViewIds out of the bundle
mViewIds = bundle.getIntArray(STATE_VIEW_IDS);
// For each id, assign to the view of same index
if (mViewIds != null) {
for (int i = 0; i < mViewIds.length; i++) {
getChildAt(i).setId(mViewIds[i]);
}
}
// Get mOriginalValue out of the bundle
mOriginalValue = getValueBackOutOfTheBundle(bundle, STATE_ORIGINAL_VALUE);
// get super parcelable back out of the bundle and pass it to
// super.onRestoreInstanceState(Parcelable)
state = bundle.getParcelable(SUPER_INSTANCE_STATE);
super.onRestoreInstanceState(state);
}
}