Ответы здесь уже хороши, но не обязательно работают для пользовательских ViewGroups. Чтобы все пользовательские представления сохранили свое состояние, необходимо переопределить onSaveInstanceState()и onRestoreInstanceState(Parcelable state)в каждом классе. Вы также должны убедиться, что все они имеют уникальные идентификаторы, независимо от того, накачаны они из xml или добавлены программно.
То, что я придумал, было удивительно похоже на ответ Kobor42, но ошибка осталась, потому что я программно добавлял виды в пользовательскую группу ViewGroup, а не назначал уникальные идентификаторы.
Ссылка, совместно используемая mato, будет работать, но это означает, что ни один из отдельных видов не управляет своим собственным состоянием - все состояние сохраняется в методах ViewGroup.
Проблема заключается в том, что когда несколько из этих ViewGroups добавляются в макет, идентификаторы их элементов из XML больше не являются уникальными (если они определены в XML). Во время выполнения вы можете вызвать статический метод, View.generateViewId()чтобы получить уникальный идентификатор для представления. Это доступно только из API 17.
Вот мой код из ViewGroup (он абстрактный, а mOriginalValue является переменной типа):
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);
}
}