Puedes agregar una IU basada en Compose a una app existente que use un diseño basado en View.
Para crear una pantalla nueva basada íntegramente en Compose, haz que tu actividad llame al método setContent() y pasa las funciones de componibilidad que quieras.
class ExampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // In here, we can call composables! MaterialTheme { Greeting(name = "compose") } } } } @Composable fun Greeting(name: String) { Text(text = "Hello $name!") }
Este código es similar al que se encuentra en una app exclusivamente de Compose.
ViewCompositionStrategy para ComposeView
ViewCompositionStrategy
define cuándo se debe descartar la composición. El valor predeterminado,
ViewCompositionStrategy.Default,
descarta la composición cuando la
ComposeView
subyacente se separa de la ventana, a menos que forme parte de un contenedor de agrupación, como
RecyclerView. En una app de Compose con una sola actividad, este comportamiento predeterminado es el que deseas. Sin embargo, si agregas Compose de forma incremental a tu base de código, este comportamiento puede provocar la pérdida de estado en algunas situaciones.
Para cambiar ViewCompositionStrategy, llama al setViewCompositionStrategy()
método y proporciona una estrategia diferente.
En la siguiente tabla, se resumen las diferentes situaciones en las que puedes usar ViewCompositionStrategy:
ViewCompositionStrategy |
Descripción y situación de interoperabilidad |
|---|---|
DisposeOnDetachedFromWindow |
La composición se descartará cuando la ComposeView subyacente se separe de la ventana. Desde entonces, se reemplazó por DisposeOnDetachedFromWindowOrReleasedFromPool.Situación de interoperabilidad: * ComposeView ya sea que sea el único elemento en la jerarquía de vistas o en el contexto de una pantalla mixta de View/Compose (no en Fragment). |
DisposeOnDetachedFromWindowOrReleasedFromPool (Predeterminado) |
Similar a DisposeOnDetachedFromWindow, cuando la composición no está en un contenedor de agrupación, como RecyclerView. Si está en un contenedor de agrupación, se descartará cuando el contenedor de agrupación en sí se separe de la ventana o cuando se descarte el elemento (es decir, cuando el grupo esté lleno).Situación de interoperabilidad: * ComposeView ya sea que sea el único elemento en la jerarquía de vistas o en el contexto de una pantalla mixta de View/Compose (no en Fragment).* ComposeView como un elemento en un contenedor de agrupación, como RecyclerView. |
DisposeOnLifecycleDestroyed |
La composición se descartará cuando se destruya el Lifecycle.Situación de interoperabilidad * ComposeView en la vista de un fragmento. |
DisposeOnViewTreeLifecycleDestroyed |
La composición se descartará cuando se destruya el Lifecycle que posee el LifecycleOwner que muestra ViewTreeLifecycleOwner.get de la siguiente ventana a la que está adjunta la vista.Situación de interoperabilidad: * ComposeView en la vista de un fragmento.* ComposeView en una vista en la que aún no se conoce el ciclo de vida. |
ComposeView en Fragments (paso de transición)
Si quieres incorporar contenido de la IU de Compose a un fragmento o un diseño de vistas existente, usa ComposeViewy llama a susetContent()método. ComposeView es una View de Android.
Puedes colocar ComposeView en tu diseño XML como cualquier otro elemento View:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <androidx.compose.ui.platform.ComposeView android:id="@+id/compose_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
En el código fuente de Kotlin, aumenta el diseño del recurso de diseño que se define en XML. Luego, obtén la
ComposeView con el ID de XML, establece la estrategia de composición que mejor se adapte a
la View del host y llama a setContent() para usar Compose.
class ExampleFragmentXml : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { val view = inflater.inflate(R.layout.fragment_example, container, false) val composeView = view.findViewById<ComposeView>(R.id.compose_view) composeView.apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { // In Compose world MaterialTheme { Text("Hello Compose!") } } } return view } }
Como alternativa, también puedes usar la vinculación de vistas para obtener referencias a ComposeView haciendo referencia a la clase de vinculación generada para tu archivo de diseño XML:
class ExampleFragment : Fragment() { private var _binding: FragmentExampleBinding? = null // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentExampleBinding.inflate(inflater, container, false) val view = binding.root binding.composeView.apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { // In Compose world MaterialTheme { Text("Hello Compose!") } } } return view } override fun onDestroyView() { super.onDestroyView() _binding = null } }
Figura 1: Muestra el resultado del código que agrega elementos de Compose a una jerarquía de la IU de View. El texto "Hello Android!" se muestra en un widget TextView. El texto "Hello Compose!" se muestra en un elemento de texto de Compose.
También puedes incluir una ComposeView directamente en un fragmento si toda tu pantalla está compilada con Compose, por lo que no necesitas usar un archivo de diseño XML.
class ExampleFragmentNoXml : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { MaterialTheme { // In Compose world Text("Hello Compose!") } } } } }
Varias instancias de ComposeView en el mismo diseño
Si hay varios elementos ComposeView en el mismo diseño, cada uno debe tener un ID único para que savedInstanceState funcione.
class ExampleFragmentMultipleComposeView : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = LinearLayout(requireContext()).apply { addView( ComposeView(requireContext()).apply { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) id = R.id.compose_view_x // ... } ) addView(TextView(requireContext())) addView( ComposeView(requireContext()).apply { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) id = R.id.compose_view_y // ... } ) } }
Los IDs de ComposeView se definen en el archivo res/values/ids.xml:
<resources> <item name="compose_view_x" type="id" /> <item name="compose_view_y" type="id" /> </resources>
Obtén una vista previa de los elementos componibles en el editor de diseño
También puedes obtener una vista previa de los elementos componibles en el editor de diseño para tu diseño XML que contiene un ComposeView. Si lo haces, podrás ver cómo se ven tus elementos componibles en un diseño mixto de Views y Compose.
Supongamos que quieres mostrar el siguiente elemento componible en el editor de diseño. Ten en cuenta que los elementos componibles anotados con @Preview son buenos candidatos para obtener una vista previa en el editor de diseño.
@Preview @Composable fun GreetingPreview() { Greeting(name = "Android") }
Para mostrar este elemento componible, usa el atributo de herramientas tools:composableName y establece su valor en el nombre completamente calificado del elemento componible para obtener una vista previa en el diseño.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.compose.ui.platform.ComposeView android:id="@+id/my_compose_view" tools:composableName="com.example.compose.snippets.interop.InteroperabilityAPIsSnippetsKt.GreetingPreview" android:layout_height="match_parent" android:layout_width="match_parent"/> </LinearLayout>
