Fragmentos, DialogFragment y Rotación de Pantalla

Tengo una actividad que llama a setContentView con este XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <fragment android:name="org.vt.indiatab.GroupFragment" android:id="@+id/home_groups" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /> <..some other fragments ...> </LinearLayout> 

El GroupFragment extiende Fragment, y todo está bien allí. Sin embargo, muestro un DialogFragment dentro de GroupFragment. Esto muestra correctamente, sin embargo, cuando la pantalla gira, obtengo un cierre de fuerza.

¿Cuál es la forma correcta de mostrar un DialogFragment desde otro Fragmento que no sea DialogFragment.show (FragmentManager, String)?

Hay un error en la biblioteca de compatibilidad que puede causar esto. Trate de poner esto en usted dialogfragment:

 @Override public void onDestroyView() { if (getDialog() != null && getRetainInstance()) getDialog().setOnDismissListener(null); super.onDestroyView(); } 

También sugiero establecer el diálogo como retenido, por lo que no se despidió después de la rotación. Poner "setRetainInstance (true)"; Por ejemplo, en el método onCreate ().

Aceptar, mientras que el método de Zsombor funciona, esto se debe a mí ser inexperto con Fragmentos y su solución causa problemas con el saveInstanceState Bundle .

Aparentemente (al menos para un DialogFragment), debe ser una public static class . Usted también DEBE escribir su propio static DialogFragment newInstance() . Esto se debe a que la clase Fragment llama al método newInstance en su método instantiate() .

Así que en conclusión, usted DEBE escribir sus DialogFragments así:

 public static class MyDialogFragment extends DialogFragment { static MyDialogFragment newInstance() { MyDialogFragment d = new MyDialogFragment(); return d; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { ... } } 

Y muéstrales con:

 private void showMyDialog() { MyDialogFragment d = MyDialogFragment.newInstance(); d.show(getFragmentManager(), "dialog"); } 

Esto puede ser exclusivo de la biblioteca ActionBarSherlock, pero las muestras oficiales en la documentación del SDK utilizan este paradigma también.

Para superar el Bundle siempre siendo nulo, lo onSaveInstanceState en un campo estático en onSaveInstanceState . Es un olor a código, pero la única solución que encontré para restaurar el diálogo y guardar el estado.

La referencia del Bundle debe onDestroy en onDestroy .

 @Override public void onCreate(Bundle savedInstanceState) { if (savedInstanceState == null) savedInstanceState = HackishSavedState.savedInstanceState; setRetainInstance(true); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { if (savedInstanceState == null) savedInstanceState = HackishSavedState.savedInstanceState; ... } @Override public void onDestroyView() // necessary for restoring the dialog { if (getDialog() != null && getRetainInstance()) getDialog().setOnDismissListener(null); super.onDestroyView(); } @Override public void onSaveInstanceState(Bundle outState) { ... HackishSavedState.savedInstanceState = outState; super.onSaveInstanceState(outState); } @Override public void onDestroy() { HackishSavedState.savedInstanceState = null; super.onDestroy(); } private static class HackishSavedState { static Bundle savedInstanceState; } 

Utilicé una mezcla de las soluciones presentadas y añadí una cosa más. Esta es mi solución final:

Utilicé setRetainInstance (true) en el onCreateDialog; Utilicé esto:

 public void onDestroyView() { if (getDialog() != null && getRetainInstance()) getDialog().setDismissMessage(null); super.onDestroyView(); } 

Y como una solución de la savedInstanceState no funciona, he creado una clase privada llamada StateHolder (de la misma manera que un titular es crear para una listView):

 private class StateHolder { String name; String quantity; } 

Yo salvo el estado de esta manera:

 @Override public void onSaveInstanceState(Bundle savedInstanceState) { super.onSaveInstanceState(savedInstanceState); stateHolder = new StateHolder(); stateHolder.name = actvProductName.getText().toString(); stateHolder.quantity = etProductQuantity.getText().toString(); } 

En el método onDismiss establecí el stateHolder de nuevo a null. Cuando se crea el diálogo, verifica si el stateHolder no es nulo para recuperar el estado o simplemente inicializar todo normalmente.

He resuelto este problema con las respuestas de @ ZsomborErdődy-Nagy y @AndyDennie. Debes subclase esta clase y en tu fragmento padre llamar a setRetainInstance(true) , y dialogFragment.show(getFragmentManager(), "Dialog");

  public class AbstractDialogFragment extends DialogFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); } @Override public void onDestroyView() { if (getDialog() != null && getRetainInstance()) getDialog().setDismissMessage(null); super.onDestroyView(); } } 

Tuve un problema similar, sin embargo ninguno de los anteriores funcionó para mí. Al final necesitaba crear el fragmento en código en vez de en el diseño XML.

Consulte: Sustitución de fragmentos y cambio de orientación

Me encontré con esto en mi proyecto y ninguna de las soluciones anteriores ayudó.

Si la excepción parece algo así como

 java.lang.RuntimeException: Unable to start activity ComponentInfo{ ... Caused by: java.lang.IllegalStateException: Fragment.... did not create a view. 

Es causado por un problema con un identificador de contenedor que se utiliza después de la rotación. Vea este boleto para más detalles:

https://code.google.com/p/android/issues/detail?id=18529

Básicamente, puede prevenir el bloqueo asegurándose de que todos los fragmentos xml tengan una etiqueta definida en el diseño. Esto evita que se produzca la condición de retroceso si gira cuando un fragmento es visible.

En mi caso pude aplicar esta corrección sin tener que sobrescribir onDestroyView () o setRetainInstance (true), que es la recomendación común para esta situación.

Encontré este problema y el truco de onDestroyView() no funcionaba. Resultó que era porque estaba haciendo una creación bastante intensa de diálogo en onCreate() . Esto incluyó guardar una referencia al AlertDialog , que luego volvería en onCreateDialog() .

Cuando moví todo este código a onCreateDialog() y dejé de retener una referencia al diálogo, empezó a funcionar de nuevo. Espero que estaba violando uno de los invariants que DialogFragment tiene sobre la gestión de su diálogo.

En onCreate() llame a setRetainInstance(true) y luego incluya esto:

 @Override public void onDestroyView() { if (getDialog() != null && getRetainInstance()) { getDialog().setOnDismissMessage(null); } super.onDestroyView(); } 

Cuando llama a setRetainInstance(true) en onCreate (), onCreate () ya no se llamará a través de los cambios de orientación, pero onCreateView () seguirá siendo llamado.

Así que aún puede guardar el estado en su paquete en onSaveInstanceState() y luego recuperarlo en onCreateView() :

 @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("myInt", myInt); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.my_layout, container); if (savedInstanceState != null) { myInt = savedInstanceState.getInt("myInt"); } ... return view; } 
  • DialogFragment y botón Atrás
  • invalidateOptionsMenu no funciona en fragmento
  • ViewPager en blanco en la parte posterior de otro fragmento
  • ¿Cómo manejar varios accesos a medios sociales y sesiones de flujo en Android?
  • Pasar la consulta de búsqueda ActionBar para fragmentar
  • Cómo mantener sólo una instancia de un fragmento, al cambiar con NavigationDrawer?
  • Práctica recomendada para iniciar AsyncTask desde la vista personalizada
  • Cómo borrar la pila trasera de fragmentos de Android sin reanudar fragmentos intermedios
  • Utilizar el editor de diseño de manera efectiva en diseños con fragmentos no estáticos
  • ViewPager + Adaptador en Fragmento => laggy swiping
  • TabLayout dentro de la barra de herramientas
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.