Durante el tiempo de ejecución, un FragmentManager
puede agregar, quitar, reemplazar y realizar otras acciones con fragmentos en respuesta a la interacción del usuario. Cada conjunto de cambios de fragmento que confirmes se denomina transacción, y puedes especificar qué hacer dentro de la transacción mediante las API que proporciona la clase FragmentTransaction
. Puedes agrupar varias acciones en una sola transacción; por ejemplo, una transacción puede agregar o reemplazar varios fragmentos. Esta agrupación puede ser útil para cuando se muestran varios fragmentos del mismo nivel en la misma pantalla, como en el caso de las vistas divididas.
Puedes guardar cada transacción en una pila de actividades administrada por el FragmentManager
, lo que le permite al usuario navegar hacia atrás por los cambios realizados en el fragmento, de forma similar a navegar hacia atrás por las actividades.
Puedes obtener una instancia de FragmentTransaction
desde el FragmentManager
si llamas a beginTransaction()
, como se muestra en el siguiente ejemplo:
Kotlin
val fragmentManager = ... val fragmentTransaction = fragmentManager.beginTransaction()
Java
FragmentManager fragmentManager = ... FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
La llamada final en cada FragmentTransaction
debe confirmar la transacción.
La llamada commit()
señala al FragmentManager
que todas las operaciones se agregaron a la transacción.
Kotlin
val fragmentManager = ... // The fragment-ktx module provides a commit block that automatically // calls beginTransaction and commit for you. fragmentManager.commit { // Add operations here }
Java
FragmentManager fragmentManager = ... FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); // Add operations here fragmentTransaction.commit();
Cómo permitir el reordenamiento de los cambios de estado de los fragmentos
Cada FragmentTransaction
debe usar setReorderingAllowed(true)
:
Kotlin
supportFragmentManager.commit { ... setReorderingAllowed(true) }
Java
FragmentManager fragmentManager = ... fragmentManager.beginTransaction() ... .setReorderingAllowed(true) .commit();
Para lograr la compatibilidad del comportamiento, la marca de orden no está habilitada de forma predeterminada.
Sin embargo, es necesaria para permitir que FragmentManager
ejecute correctamente tu FragmentTransaction
, en especial cuando opera en la pila de actividades y ejecuta animaciones y transiciones. Habilitar la marca garantiza que, si se ejecutan varias transacciones, los fragmentos intermedios (es decir, los que se agregan y, luego, se reemplazan de inmediato) no experimenten cambios del ciclo de vida, y que sus animaciones o transiciones no se ejecuten. Ten en cuenta que esta marca afecta tanto la ejecución inicial de la transacción como la reversión de la transacción con popBackStack()
.
Cómo agregar y quitar fragmentos
Para agregar un fragmento a un FragmentManager
, llama a add()
en la transacción. Este método recibe el ID del contenedor del fragmento, así como el nombre de la clase del fragmento que deseas agregar. El fragmento agregado pasa al estado RESUMED
. Te recomendamos que el contenedor sea una FragmentContainerView
que forme parte de la jerarquía de vistas.
Para quitar un fragmento del host, llama a remove()
y pasa una instancia de fragmento que se recuperó del administrador de fragmentos a través de findFragmentById()
o findFragmentByTag()
.
Si previamente se agregó la vista del fragmento a un contenedor, la vista se quitará del contenedor en este momento. El fragmento que se quita pasa al estado DESTROYED
.
Usa replace()
para reemplazar un fragmento existente en un contenedor por una instancia de la nueva clase de fragmento que proporciones. Llamar a replace()
equivale a llamar a remove()
con un fragmento en un contenedor y agregar un fragmento nuevo al mismo contenedor.
En el siguiente fragmento de código, se muestra cómo puedes reemplazar un fragmento por otro:
Kotlin
// Create new fragment val fragmentManager = // ... // Create and commit a new transaction fragmentManager.commit { setReorderingAllowed(true) // Replace whatever is in the fragment_container view with this fragment replace<ExampleFragment>(R.id.fragment_container) }
Java
// Create new fragment and transaction FragmentManager fragmentManager = ... FragmentTransaction transaction = fragmentManager.beginTransaction(); transaction.setReorderingAllowed(true); // Replace whatever is in the fragment_container view with this fragment transaction.replace(R.id.fragment_container, ExampleFragment.class, null); // Commit the transaction transaction.commit();
En este ejemplo, una instancia nueva de ExampleFragment
reemplaza el fragmento, si hay alguno, que se encuentra en ese momento en el contenedor de diseño identificado por R.id.fragment_container
.
De forma predeterminada, los cambios realizados en una FragmentTransaction
no se agregan a la pila de actividades. Para guardar esos cambios, puedes llamar a addToBackStack()
en la FragmentTransaction
. Si deseas obtener más información, consulta el administrador de fragmentos.
La confirmación es asíncrona
Llamar a commit()
no realiza la transacción inmediatamente. En cambio, la transacción se programará para ejecutarse en el subproceso de IU principal en cuanto pueda hacerlo. Sin embargo, si es necesario, puedes llamar a commitNow()
a fin de ejecutar la transacción del fragmento en tu subproceso de IU de inmediato.
Ten en cuenta que commitNow
no es compatible con addToBackStack
. Como alternativa, puedes ejecutar todas las FragmentTransactions
pendientes enviadas por las llamadas de commit()
aún no ejecutadas llamando a executePendingTransactions()
. Este enfoque es compatible con addToBackStack
.
Para la gran mayoría de los casos de uso, solo necesitas commit()
.
El orden de las operaciones es significativo
El orden en el que realizas operaciones en una FragmentTransaction
es significativo, en especial cuando se usa setCustomAnimations()
. Este método aplica las animaciones determinadas a todas las operaciones de fragmentos que la siguen.
Kotlin
supportFragmentManager.commit { setCustomAnimations(enter1, exit1, popEnter1, popExit1) add<ExampleFragment>(R.id.container) // gets the first animations setCustomAnimations(enter2, exit2, popEnter2, popExit2) add<ExampleFragment>(R.id.container) // gets the second animations }
Java
getSupportFragmentManager().beginTransaction() .setCustomAnimations(enter1, exit1, popEnter1, popExit1) .add(R.id.container, ExampleFragment.class, null) // gets the first animations .setCustomAnimations(enter2, exit2, popEnter2, popExit2) .add(R.id.container, ExampleFragment.class, null) // gets the second animations .commit()
Cómo limitar el ciclo de vida del fragmento
FragmentTransactions
puede afectar el estado del ciclo de vida de los fragmentos individuales agregados dentro del alcance de la transacción. Cuando creas una FragmentTransaction
, setMaxLifecycle()
establece un estado máximo para el fragmento determinado. Por ejemplo, ViewPager2
usa setMaxLifecycle()
a fin de limitar los fragmentos fuera de la pantalla al estado STARTED
.
Cómo mostrar y ocultar vistas de fragmentos
Usa los métodos show()
y hide()
de FragmentTransaction
para mostrar y ocultar la vista de fragmentos agregados a un contenedor.
Estos métodos establecen la visibilidad de las vistas del fragmento sin afectar el ciclo de vida de este.
Si bien no necesitas usar una transacción de fragmento para activar o desactivar la visibilidad de las vistas dentro de un fragmento, estos métodos resultan útiles en casos en los que quieres que se asocien los cambios del estado de visibilidad con las transacciones en la pila de actividades.
Cómo conectar y desconectar fragmentos
El método detach()
de FragmentTransaction
desvincula el fragmento de la IU, lo que destruye su jerarquía de vistas. El fragmento permanece en el mismo estado (STOPPED
) que tenía cuando se coloca en la pila de actividades.
Esto significa que se quitó el fragmento de la IU, pero aún lo administra el administrador de fragmentos.
El método attach()
vuelve a conectar un fragmento que se había desconectado con anterioridad.
Esto hace que su jerarquía de vistas se vuelva a crear, se conecte a la IU y se muestre.
Dado que una FragmentTransaction
se trata como un conjunto único de operaciones atómicas, las llamadas a detach
y attach
en la misma instancia del fragmento y en la misma transacción se cancelan entre sí. De esta manera, evitan la destrucción de la IU del fragmento y su inmediata recreación. Si deseas desconectar y, luego, reconectar un fragmento, usa transacciones independientes, separadas por executePendingOperations()
si usas commit()
.