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
, elimina la composición cuando el ComposeView
subyacente se separa de la ventana, a menos que forme parte de un contenedor de grupo, como un RecyclerView
. En una app de solo Compose de una sola actividad, este comportamiento predeterminado es lo 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 el ViewCompositionStrategy
, llama al método setViewCompositionStrategy()
y proporciona una estrategia diferente.
En la siguiente tabla, se resumen las diferentes situaciones en las que puedes usar ViewCompositionStrategy
:
ViewCompositionStrategy |
Descripción y escenario de interoperabilidad |
---|---|
DisposeOnDetachedFromWindow |
La composición se descartará cuando se desvincule el ComposeView subyacente de la ventana. Desde entonces, se reemplazó por DisposeOnDetachedFromWindowOrReleasedFromPool .Situación de interoperabilidad: * ComposeView ya sea el único elemento en la jerarquía de View 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 un RecyclerView . Si está en un contenedor de grupo, se eliminará cuando el contenedor de grupo se desconecte de la ventana o cuando se descarte el elemento (es decir, cuando el grupo esté lleno).Situación de interoperabilidad: * ComposeView ya sea el único elemento en la jerarquía de View 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 eliminará cuando se destruya el Lifecycle proporcionado.Situación de interoperabilidad * ComposeView en la vista de un fragmento. |
DisposeOnViewTreeLifecycleDestroyed |
La composición se eliminará cuando se destruya el Lifecycle que pertenece al LifecycleOwner que muestra ViewTreeLifecycleOwner.get de la siguiente ventana a la que se 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
Si quieres incorporar contenido de la IU de Compose a un fragmento o un diseño de View existente, usa ComposeView
y llama a su método setContent()
. 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 ID 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>
Cómo obtener una vista previa de los elementos componibles en el editor de diseño
También puedes obtener una vista previa de los elementos componibles dentro del editor de diseño para tu diseño XML que contiene un ComposeView
. De esta manera, puedes ver cómo se ven tus elementos componibles dentro de 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 con anotaciones @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>
Próximos pasos
Ahora que conoces las APIs de interoperabilidad para usar Compose en Views, obtén información sobre cómo usar Views en Compose.
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Otras consideraciones
- Estrategia de migración {:#migration-strategy}
- Cómo comparar el rendimiento de Compose y View