13

Tengo problemas para entender cómo administrar correctamente Fragment s en un patrón típico de diseño de detalles de lista.Cómo administrar el estado de la IU y la pila posterior en un diseño de panel simple/doble

Mi diseño está trabajando muy bien y se estructura como esta para la vista horizontal (doble panel):

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout ... > 
    <FrameLayout android:id="@+id/list" ... /> 
    <FrameLayout android:id="@+id/container" ... /> 
</LinearLayout> 

Y así durante la vista vertical (solo panel):

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout android:id="@+id/container" ... /> 

I también tiene un refs.xml en res/values-w600dp/ para asegurarse de que el diseño apropiado se carga en función del ancho de la pantalla del dispositivo.

Cuando se selecciona un elemento de la lista, la vista horizontal debe mostrar la lista y los detalles uno al lado del otro, mientras que la vista vertical debe mostrar solo los detalles en pantalla completa. Cuando no se ha seleccionado nada, la vista horizontal debe mostrar la izquierda a la izquierda y el espacio en blanco a la derecha, mientras que la vista vertical debe mostrar solo la lista a pantalla completa.

example

Sin embargo, aquí es donde tengo problemas:

  • hacer yo utilizo un "principal" Activity para la lista + detalles diseño opcional, y otros "detalles" Activity para el retrato, diseño solo de detalles? Esto parece ser lo que hace el ejemplo Fragments guide. He llegado a este acuerdo para trabajar en general, pero ¿cómo puedo mantener el estado de mi fragmento de detalles cuando cambia la orientación?

    considerar el caso opuesto se muestra arriba - rotación de vertical a horizontal mientras que los detalles son visibles significa los detalles Activity tendrían que ser finish() ed por lo que el principal Activity podría mostrar la disposición de dos paneles, pero esto también destruye los detalles fragmento y es savedInstanceState. Si el usuario ha tipeado información en los campos EditText en el fragmento de detalles, luego gira el dispositivo, ¿cómo puedo preservar el estado de la IU completa del fragmento de detalles cuando lo agrego al principal (dos paneles) Activity?

  • ¿Utilizo solo un Activity y administro el Fragment s? Esto me permite retener el estado de la IU de detalles cuando cambia la orientación (porque Android se encarga de esto automáticamente), pero se vuelve complicado cuando se trata de la pila de respaldo.

    Considere el caso en la imagen - girando de paisaje a retrato cuando los detalles se muestran deben mostrar los detalles de un solo panel, pero ¿cómo administro correctamente la pila posterior y ActionBar icono de inicio para mostrar la lista ¿cristal? Volviendo al paisaje también necesitaría deshacer cualquier manipulación de pila que hice anteriormente, ya que ambos fragmentos serán visibles a la vez.

Después de un poco más de búsqueda, me encontré dos preguntas similares (Switch from dual pane to single pane on orientation change maintaining fragment stack y Retain Fragment state between Activities), pero mi situación es un poco diferente porque no estoy tratando de adaptar esta funcionalidad, pero mejor plan para que en la delantera. ¿Qué me estoy perdiendo? Seguramente Android puede administrar tanto la pila posterior (como en el caso de Activity múltiple) y el estado de la IU (como en el caso único Activity) a la vez, ¿verdad?

Respuesta

6

Lo resolví yendo a la ruta de actividades múltiples. See my answer to "Retain Fragment state between Activities".

La clave estaba usando FragmentManager.saveFragmentInstanceState() para guardar el estado de la interfaz de usuario del fragmento y Fragment.setInitialSavedState() para restaurarlo al crear el mismo fragmento en otra actividad.

Para mis propósitos, encontré que necesitaba guardar el estado de IU en dos casos. Creé un método de ayuda public void saveState() dentro de mi fragmento y lo llamo desde el propio método onPause() del fragmento, así como de mi actividad "principal" inmediatamente antes de usar replace() para adjuntar una nueva instancia del fragmento al diseño de doble panel.

Todavía estoy interesado en saber si la manipulación de la pila necesaria para este tipo de escenario de diseño de panel simple/doble es posible o si el enfoque de actividad única requeriría anular onBackPressed y simular manualmente una pila posterior.

4

Es posible usar solo una actividad, pero tendrá que administrar la backstack en orientación vertical usted mismo.

Al describir el comportamiento de la aplicación, podría ser de 4 estados:

  • Estado A: retrato, que muestra el fragmento de la lista.
  • Estado B: retrato, que muestra el fragmento de detalles con el fragmento de lista en la pila posterior.
  • Estado C: paisaje, que muestra el fragmento de lista a la izquierda y un espacio en blanco a la derecha.
  • Estado D: paisaje, que muestra el fragmento de la lista y el fragmento de detalles uno al lado del otro.

Imagine que está en estado D (con ambos fragmentos, llamémosle FA y FB), y cambia la orientación del teléfono. El siguiente estado debe ser el estado B, pero el problema es que el diseño de retrato solo tiene uno FrameLayout. Utilizando la siguiente como el diseño de panel simple:

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout android:id="@+id/list" ... /> 

Android recreará FA y tendrá que atribuye a que FrameLayout. FB, por otro lado, también se volverá a crear, pero no tendrá un contenedor asociado, por lo que no se mostrará. En este punto, podría crear otro fragmento, FB2 con los mismos contenidos que FB, y usarlo para reemplazar FA. Tendrá FA-FB2 en su backstack y FB ocultos.

Si cambia la orientación de nuevo (esperando el estado D), se puede utilizar para hacer estallar onSaveInstanceState() FB2 del backstack con popBackStack(), teniendo así una vez más la FA y FB. Antes de eliminar FB2, también puede copiar su contenido a FB. Cuando la aplicación vuelva a estar en el estado D, FB tendrá su FrameLayout.

Habría algunas otras transiciones y situaciones de las que tendría que ocuparse, pero la idea principal sería esa.

No es una solución muy elegante, así que estoy seguro de que tiene que ser una forma mejor, quizás más eficiente (sin replicar fragmentos, por ejemplo) para resolver este problema.

Cuestiones relacionadas