Las respuestas aquí ya son geniales, pero no necesariamente funcionan para grupos de vista personalizados. Para que todas las Vistas personalizadas conserven su estado, debe anular onSaveInstanceState()
y onRestoreInstanceState(Parcelable state)
en cada clase. También debe asegurarse de que todos tengan identificadores únicos, ya sea que estén inflados desde xml o agregados mediante programación.
Lo que se me ocurrió fue notablemente como la respuesta de Kobor42, pero el error se mantuvo porque estaba agregando las Vistas a un Grupo de Vistas personalizado mediante programación y no asignando identificadores únicos.
El enlace compartido por mato funcionará, pero significa que ninguna de las Vistas individuales gestiona su propio estado: todo el estado se guarda en los métodos ViewGroup.
El problema es que cuando se agregan múltiples de estos ViewGroups a un diseño, los identificadores de sus elementos del xml ya no son únicos (si está definido en xml). En tiempo de ejecución, puede llamar al método estático View.generateViewId()
para obtener una identificación única para una vista. Esto solo está disponible en API 17.
Aquí está mi código del ViewGroup (es abstracto, y mOriginalValue es una variable de tipo):
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);
}
}