Android Honeycomb: ¿Cómo cambiar fragmentos en FrameLayout, sin volver a crearlos?

¿Es posible cambiar entre Fragmentos sin volver a crearlos todo el tiempo? ¿Si es así, cómo?

En la documentación encontré un ejemplo de cómo reemplazar Fragmentos.

// Create new fragment and transaction Fragment newFragment = new ExampleFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); // Replace whatever is in the fragment_container view with this fragment, // and add the transaction to the back stack transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); // Commit the transaction transaction.commit(); 

Pero no quiero crear mis Fragmentos desde el principio cada vez que los necesito.

También encontré este ejemplo de ocultar / mostrar Fragmentos:

 // The content view embeds two fragments; now retrieve them and attach // their "hide" button. FragmentManager fm = getFragmentManager(); addShowHideListener(R.id.frag1hide, fm.findFragmentById(R.id.fragment1)); addShowHideListener(R.id.frag2hide, fm.findFragmentById(R.id.fragment2)); 

Pero, ¿cómo crear un fragmento con un ID fuera de un archivo XML?

Creo que esto podría estar relacionado con esta pregunta , pero no hay una respuesta. : /

Muchas gracias de antemano, medusa

Editar:

Así es como lo hago ahora:

 Fragment shown = fragmentManager.findFragmentByTag(shownFragment); //... FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); if (shown != null) fragmentTransaction.hide(shown); //switch statetement for menu selection, just one example: SettingsFragment set = (SettingsFragment) fragmentManager.findFragmentByTag(SET); Toast.makeText(this, "Settings:" + set, Toast.LENGTH_LONG).show(); if (set == null) { set = new SettingsFragment(); fragmentTransaction.add(R.id.framelayout_content, set, SET); } else fragmentTransaction.show(set); shownFragment = SET; fragmentTransaction.commit(); 

Si llamo a la configuración, luego otra cosa, y luego volver a la configuración, el brindis me da "null" primero y "Settings: SettingsFragment {40ef …" segundo.

Sin embargo, si reemplazo fragmentTransaction.add(R.id.framelayout_content, set, SET); Con fragmentTransaction.replace(R.id.framelayout_content, set, SET); Sigo recibiendo "null", "null", "null" … por lo que no parece encontrar el Fragmento por etiqueta.

Edit2:

Añadiendo fragmentTransaction.addToBackStack(null); Hizo el truco. 🙂 Esto ahorra todo el esconder / memorizar qué fragmento se muestra parte así que supongo que es la solución más elegante para esto.

He encontrado este tutorial bastante útil sobre el tema.

Editar3:

Mirando mi código me di cuenta de que podía deshacerse de algunas partes, así que lo cambié a:

 FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); if (shown != null) fragmentTransaction.hide(shown); Settings set = (Settings) fragmentManager.findFragmentByTag(SET); if (set == null) set = new Settings(); fragmentTransaction.replace(R.id.framelayout_content, set, SET); fragmentTransaction.addToBackStack(null); fragmentTransaction.commit(); 

Sin embargo, esto invocó una IllegalStateException: Fragment already added , casi igual que aquí . ¿Hay una manera fácil de prevenir esto? De lo contrario creo que podría cambiar de nuevo a la ocultar / mostrar poco.

Podría depender de lo que usted está tratando de evitar ser re-creado.

 // Replace whatever is in the fragment_container view with this fragment, // and add the transaction to the back stack transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); 

En el ejemplo de ejemplo al pulsar el botón de nuevo de su nuevo fragmento, se mostrará el fragmento anterior (obtendrá un onCreateView, onActivityCreated pero no onCreate) para que el fragmento no se vuelva a crear como tal. En cuanto a newFragment usted puede todavía guardarlo alrededor si usted planea usarlo otra vez que pone al día cualquier estado interno según lo requerido en decir onCreate o onActivityCreated.

EDITAR:

Si simplemente tiene una lista de menús con cada entrada invocando un fragmento diferente en un panel derecho, a continuación, añadir a la pila de atrás no es lo que desea. Para esto, podrías salir con la llamada add(...) en cada fragmento up-front y simplemente ocultar / mostrar cada fragmento según sea necesario (no he probado esto). De lo contrario sugeriría mantener una referencia a cada fragmento, llamada replace(...) en la selección de un elemento de menú diferente asegurándose de que no se agrega a la pila trasera.

Para evitar la

IllegalStateException: Fragmento ya agregado

He encontrado una solución que funciona bien para mí: use remove(AFrag) y add(BFrag) en su transacción, en lugar de replace() .

Parece que es un error: cuarto comentario en la respuesta aceptada .

 fragmentTransactionOnClick.setTransition(FragmentTransaction.TRANSIT_EXIT_MASK); 

Si agrega el archivo. setTransition.exit transit_exit_mask entonces las vistas anteriores no aparecerán

Encontré una forma de usar la función "tag":

 //... fragmentTransaction.add(R.id.framelayout_content, fragment1, "foo"); fragmentTransaction.add(R.id.framelayout_content, fragment2, "bar"); //... fragmentManager.findFragmentByTag("foo"); fragmentManager.findFragmentByTag("bar"); 

Sin embargo, esto parece funcionar un poco asincrónicamente. Llamar findFragmentByTag inmediatamente después de la commit devolverá null . Sólo más tarde, en mi caso en un evento OnOptionsItemSelected , los fragmentos fueron encontrados.

También hay una función llamada findFragmentById(int) , pero no es muy útil. El Id – si no se especifica en un diseño XML – es el mismo que el del contenedor, por lo que en este caso R.id.framelayout_content . Si más adelante llama a la función con este ID, sólo podrá acceder a uno de los Fragmentos adjuntos. (Supongo que es el último, pero no lo he comprobado, aunque parece ser siempre el mismo).

Yo no por un rápido vistazo encontrar una manera de obtener el "activo" Fragmento de mi FrameLayout, así que creo que voy a guardar la etiqueta de la última muestra Fragmento en algún lugar.

  • Tipo No coincidencia de tipo: no se puede convertir de RegisterFragment a Fragment
  • Confundido sobre el uso de Fragmentos en la aplicación
  • Java.lang.IllegalStateException: Fragmento no adjunto a la actividad
  • WebViewFragment webView es nulo después de realizar una FragmentTransaction
  • Android API TabActivity deprecation
  • Usos de etiquetas de fragmento
  • GetSupportFragmentManager () no está definido
  • Android - API de Google Maps v2 - Errores de SupportMapFragment
  • Cómo persistir los datos de fragmentos después de las transacciones backstack?
  • Los miembros de la clase en Fragmento se convierten en nulos después de pulsar el botón Inicio y esperar
  • El último elemento de Listview está cortado
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.