Cómo conservar la posición de desplazamiento en un ExpandableListView

En mi aplicación tengo una clase derivada de ExpandableListActivity. Cuando desplazo el contenido y, a continuación, cambiar la orientación del teléfono o editar un elemento y luego volver a la lista, la posición de la lista original no se conserva. He intentado dos soluciones, similares a las que he utilizado recientemente con las clases derivadas de ListActivity.

Solución 1:

protected void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); mListState = state.getParcelable(LIST_STATE); } protected void onResume() { super.onResume(); loadData(); if (mListState != null) getExpandableListView().onRestoreInstanceState(mListState); } protected void onSaveInstanceState(Bundle state) { super.onSaveInstanceState(state); mListState = getExpandableListView().onSaveInstanceState(); state.putParcelable(LIST_STATE, mListState); } 

Solución 2:

 protected void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); mListPosition = state.getInt(LIST_STATE); } protected void onResume() { super.onResume(); loadData(); getExpandableListView().setSelection(mListPosition); } protected void onSaveInstanceState(Bundle state) { super.onSaveInstanceState(state); mListPosition = getExpandableListView().getFirstVisiblePosition(); state.putInt(LIST_STATE, mListPosition); } 

Ninguna solución funciona. También he intentado combinar las dos soluciones, y esto funciona cuando edito un elemento y vuelvo a la lista, pero NO funciona cuando cambio la orientación del teléfono

¿Cualquier persona puede sugerir una buena manera de alcanzar mi meta?

Después de algunos experimentos he llegado a una solución satisfactoria, que también conserva la posición de desplazamiento fino del elemento visible superior.

De hecho, es necesario guardar y restaurar tres elementos diferentes de información: el estado de lista (por ejemplo, qué grupos se expanden), el índice del primer elemento visible y su posición de desplazamiento fino.

Desafortunadamente, parece que sólo el primero es guardado por el método onSaveInstanceState de la vista de lista expandible, por lo que los otros dos deben guardarse por separado. Esto es diferente de una vista de lista no expandible, donde aparece el método onSaveInstanceState guarda toda la información necesaria para restaurar correctamente el estado y la posición de la lista (sobre este tema, véase Mantener / Guardar / Restaurar la posición de desplazamiento al volver a ListView ).

Aquí están los fragmentos de código; En la parte superior de la clase ExpandableListActivity-derived:

 private static final String LIST_STATE_KEY = "listState"; private static final String LIST_POSITION_KEY = "listPosition"; private static final String ITEM_POSITION_KEY = "itemPosition"; private Parcelable mListState = null; private int mListPosition = 0; private int mItemPosition = 0; 

Entonces, algunas anulaciones:

 protected void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); // Retrieve list state and list/item positions mListState = state.getParcelable(LIST_STATE_KEY); mListPosition = state.getInt(LIST_POSITION_KEY); mItemPosition = state.getInt(ITEM_POSITION_KEY); } protected void onResume() { super.onResume(); // Load data from DB and put it onto the list loadData(); // Restore list state and list/item positions ExpandableListView listView = getExpandableListView(); if (mListState != null) listView.onRestoreInstanceState(mListState); listView.setSelectionFromTop(mListPosition, mItemPosition); } protected void onSaveInstanceState(Bundle state) { super.onSaveInstanceState(state); // Save list state ExpandableListView listView = getExpandableListView(); mListState = listView.onSaveInstanceState(); state.putParcelable(LIST_STATE_KEY, mListState); // Save position of first visible item mListPosition = listView.getFirstVisiblePosition(); state.putInt(LIST_POSITION_KEY, mListPosition); // Save scroll position of item View itemView = listView.getChildAt(0); mItemPosition = itemView == null ? 0 : itemView.getTop(); state.putInt(ITEM_POSITION_KEY, mItemPosition); } 

Esto funciona bien en mi dispositivo Froyo.

Esto es cómo conseguí ExpandableListView.onRestoreInstanceState y onSaveInstanceState para trabajar …

Si utiliza BaseExpandableListAdapter la implementación predeterminada de getCombinedChildId devuelve un número negativo. Si busca en el código para restaurar una lista desde la posición de desplazamiento de estado guardado, ignora los ids que son negativos. Devuelve una identificación positiva para que AbsListView onRestoreInstanceState establezca la posición de desplazamiento correctamente. Para devolver IDs positivos cambie el o de getCombinedChildId de 0x8000000000000000L (negativo) a 0x7000000000000000L (positivo) superponiendo el método en su subclase de BaseExpandableListAdapter como sigue …

  public long getCombinedChildId(long groupId, long childId) { long or = 0x7000000000000000L; long group = (groupId & 0x7FFFFFFF) << 32; long child = childId & 0xFFFFFFFF; return or | group | child; } 

Encontré otra manera de hacer que funciona para mí mantener el estado. Aqui esta el link.

http://markmail.org/message/msesxums77bdoqnx#query:+page:1+mid:utmart4ob7flh3u7+state:results

El resumen es que siempre tienes que establecer el estado, incluso si el convertView! = Null.

No conozco las repercusiones de siempre establecer el estado, pero en mi caso funciona perfectamente.

Para evitar que vuelva a cargar su actividad al cambiar la orientación del teléfono, simplemente agregue la siguiente línea a su AndroidManifest.xml en la sección de actividades:

  android:configChanges="keyboardHidden|orientation|screenSize" 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.