prefacio
Para Compose, al menos la combinación con View es perfecta.
La flexibilidad de construir la interfaz de usuario aún está garantizada:
- Si desea utilizar Compose para la nueva interfaz, puede hacerlo.
- Si Compose no lo admite, use View.
- Si no desea mover la interfaz existente, puede dejarla intacta.
- Si desea utilizar Compose para parte de la interfaz existente, puede hacerlo.
- Algunos efectos de la interfaz de usuario quieren reutilizar los anteriores, sí, se pueden incrustar directamente.
Este artículo son algunas demostraciones simples que se llaman entre sí. Se pueden copiar y pegar en el uso inicial, lo cual es muy útil.
Documentación oficial:
https://developer.android.com/jetpack/compose/interop/interop-apis
Utilice Redactar en Actividad o Fragmento para crear una interfaz de usuario
Usar Redactar en Actividad
class ExampleActivity : AppCompatActivity() {
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!")
}
Usar Componer en Fragmento
class PureComposeFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return ComposeView(requireContext()).apply {
setContent {
MaterialTheme {
Text("Hello Compose!")
}
}
}
}
}
Uso de Componer en vista
ComposeView está incrustado en Xml:
Agregado a un archivo de diseño xml sin complicacionesComposeView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/hello_world"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello from XML layout" />
<androidx.compose.ui.platform.ComposeView
android:id="@+id/compose_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Al usarlo, primero encuéntrelo de acuerdo con la identificación y luego configure el contenido:
class ComposeViewInXmlActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_compose_view_in_xml)
findViewById<ComposeView>(R.id.compose_view).setContent {
// In Compose world
MaterialTheme {
Text("Hello Compose!")
}
}
}
}
Agregar dinámicamente ComposeView
El uso en el código addView()
para agregar Vista ComposeView
también se aplica a
class ComposeViewInViewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(LinearLayout(this).apply {
orientation = VERTICAL
addView(ComposeView(this@ComposeViewInViewActivity).apply {
id = R.id.compose_view_x
setContent {
MaterialTheme {
Text("Hello Compose View 1")
}
}
})
addView(TextView(context).apply {
text = "I'm am old TextView"
})
addView(ComposeView(context).apply {
id = R.id.compose_view_y
setContent {
MaterialTheme {
Text("Hello Compose View 2")
}
}
})
})
}
}
Aquí LinearLayout
se suman tres hijos: dos ComposeView
y uno de por medio TextView
.
Actúa como un puente ComposeView
. ViewGroup
Es una Vista en sí misma, por lo que se puede mezclar en el árbol de jerarquía de la Vista para ocupar un lugar.
Su setContent()
método abre la puerta al mundo Compose, donde puede pasar al método componible para dibujar el interfaz de usuario
Uso de vistas en Compose
Hemos creado una interfaz de usuario con Compose, ¿cuándo necesitaremos incrustar View en ella?
- La vista que se utilizará no tiene una versión Compose, por ejemplo
AdView
,MapView
,WebView
. - Hay una parte de la interfaz de usuario que se escribió antes y no quiero moverla (temporalmente o para siempre), y quiero usarla directamente.
- Si no puede lograr el efecto deseado con Compose, debe usar View.
Agregar vista de Android a Componer
ejemplo:
@Composable
fun CustomView() {
val state = remember { mutableStateOf(0) }
//widget.Button
AndroidView(
factory = { ctx ->
//Here you can construct your View
android.widget.Button(ctx).apply {
text = "My Button"
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
setOnClickListener {
state.value++
}
}
},
modifier = Modifier.padding(8.dp)
)
//widget.TextView
AndroidView(factory = { ctx ->
//Here you can construct your View
TextView(ctx).apply {
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
}
}, update = {
it.text = "You have clicked the buttons: " + state.value.toString() + " times"
})
}
El puente aquí es AndroidView
que es un método componible:
@Composable
fun <T : View> AndroidView(
factory: (Context) -> T,
modifier: Modifier = Modifier,
update: (T) -> Unit = NoOpUpdate
)
La fábrica recibe un parámetro de contexto para crear una vista.
El método de actualización es una devolución de llamada, que se ejecutará después de inflar y también se ejecutará después de que cambie el valor del estado de lectura.
Usando el diseño xml en Compose
El método de uso de AndroidView en Compose mencionado anteriormente está bien para una pequeña cantidad de interfaz de usuario. ¿
Qué pasa si necesita reutilizar un diseño xml existente?
No tenga miedo, el enlace de vista está aquí.
También es muy simple de usar:
- Primero debe habilitar Ver enlace.
buildFeatures {
compose true
viewBinding true
}
- En segundo lugar, necesita un diseño xml, como
complex_layout
. - A continuación, agregue una dependencia de enlace de vista Compose:
androidx.compose.ui:ui-viewbinding
.
Luego constrúyalo, genere la clase de enlace
y estará bien
@Composable
private fun ComposableFromLayout() {
AndroidViewBinding(ComplexLayoutBinding::inflate) {
sampleButton.setBackgroundColor(Color.GRAY)
}
}
Entre ellos ComplexLayoutBinding
está la clase generada según el nombre del diseño.
AndroidViewBinding
AndroidView
El método componible todavía se llama internamente .
Mostrar fragmentos en Redactar
Esta escena suena un poco extraña, porque el concepto de diseño de Compose parece ser decir adiós a Fragment
En la interfaz de usuario creada por Compose, encuentre un lugar para mostrar un Fragment, que es un poco como poner vino añejo en una botella nueva.
Pero hay muchas escenas encontradas, tal vez realmente puedas conocerlas.
El fragmento se agrega a través de FragmentManager y requiere un contenedor de diseño.
Cambie el ejemplo anterior de ViewBinding, agregue un fragmentContainer al diseño y haga clic para mostrar Fragmento:
Column(Modifier.fillMaxSize()) {
Text("I'm a Compose Text!")
Button(
onClick = {
showFragment()
}
) {
Text(text = "Show Fragment")
}
ComposableFromLayout()
}
@Composable
private fun ComposableFromLayout() {
AndroidViewBinding(
FragmentContrainerBinding::inflate,
modifier = Modifier.fillMaxSize()
) {
}
}
private fun showFragment() {
supportFragmentManager
.beginTransaction()
.add(R.id.fragmentContainer, PureComposeFragment())
.commit()
}
La cuestión del tiempo no se considera aquí, porque hacer clic en el botón para mostrar el Fragmento retrasa el tiempo.
Si desea mostrar el Fragmento directamente durante la inicialización, se puede generar una excepción:
java.lang.IllegalArgumentException: No view found for id
Solución:
@Composable
private fun ComposableFromLayout() {
AndroidViewBinding(
FragmentContrainerBinding::inflate,
modifier = Modifier.fillMaxSize()
) {
// here is safe
showFragment()
}
}
Por lo tanto, el momento del espectáculo debe garantizar al menos que la vista del contenedor se haya inflado.
Tema y estilo
Migre la aplicación View a Compose, es posible que necesite un adaptador de tema:
https://github.com/material-components/material-components-android-compose-theme-adapter
Acerca del uso de la redacción en la aplicación de vista existente:
https://developer.android.com/jetpack/compose/interop/compose-in-existing-ui
Resumir
La combinación de Compose y View se basa principalmente en dos puentes.
Es bastante interesante:
ComposeView
En realidad es una vista de Android.AndroidView
De hecho, es un método Composable.
La compatibilidad entre Compose y View garantiza que el proyecto se pueda migrar gradualmente y también da suficiente sensación de seguridad, al igual que la migración de proyectos de Java a Kotlin en aquel entonces.