Odpowiedzi tutaj są już świetne, ale niekoniecznie działają w przypadku niestandardowych grup widoków. Aby wszystkie niestandardowe widoki zachowały swój stan, należy przesłonić onSaveInstanceState()i onRestoreInstanceState(Parcelable state)w każdej klasie. Musisz także upewnić się, że wszystkie mają unikalne identyfikatory, niezależnie od tego, czy są zawyżone z XML lub dodane programowo.
To, co wymyśliłem, było zadziwiająco podobne do odpowiedzi Kobor42, ale błąd pozostał, ponieważ programowo dodawałem Widoki do niestandardowej grupy ViewGroup i nie przypisywałem unikalnych identyfikatorów.
Łącze udostępnione przez mato będzie działać, ale oznacza to, że żaden z poszczególnych widoków nie zarządza własnym stanem - cały stan jest zapisywany w metodach ViewGroup.
Problem polega na tym, że gdy wiele z tych grup ViewGroup jest dodawanych do układu, identyfikatory ich elementów z pliku xml nie są już unikalne (jeśli są zdefiniowane w pliku xml). W czasie wykonywania można wywołać metodę statyczną, View.generateViewId()aby uzyskać unikalny identyfikator widoku. Jest to dostępne tylko w API 17.
Oto mój kod z grupy ViewGroup (jest abstrakcyjny, a mOriginalValue jest zmienną typu):
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);
}
}