将整个项目迁移到 Compose 中可能很困难,幸运的是 Jetpack Compose 提供了Compose 和 传统视图/View 互相操作 API 来在现有 XML 视图中使用 Compose,以便可以慢慢迁移到 Compose。Jetpack Compose 也提供了 API 来实现在 Compose 中使用传统视图的 API。
View 中嵌入 Compose
Jetpack Compose 提供了一个 ComposeView
,我们可以在 XML 中使用它,然后在 View 中使用 ComposeView
的 setContent
方法将 Composable
方法来绘制 UI。
-
在布局中加一个
ComposeView
<?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"> <androidx.compose.ui.platform.ComposeView android:id="@+id/composeView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
-
获得 ComposeView 添加 Composable 方法
val composeView = findViewById<ComposeView>(R.id.compose_view) composeView.setContent { Text(text = "Hello https://itmob.cn") }
当然不使用 XML 布局文件,使用代码动态添加也是可以的:
package cn.itmob.example
import android.os.Bundle
import android.widget.LinearLayout
import android.widget.LinearLayout.VERTICAL
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.ui.platform.ComposeView
class SampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_views)
setContentView(
LinearLayout(this).apply {
orientation = VERTICAL
addView(
// Add ComposeView
ComposeView(baseContext).apply {
id = R.id.compose_view
setContent {
MaterialTheme {
Text("androidx.compose.material.Text")
}
}
},
)
// Add TextView
addView(
TextView(context).apply { text = "android.widget.TextView" },
)
},
)
}
}
Compose 中嵌入 View
Jetpack Compose 是独立于传统的 Android View 系统,但在 Compose 中可以也使用 View(及 android.view.View
的子类)。
为什么要在 Compose 中使用 Android View:
- WebView,AdView 等还没有原生的 Compose 版本
- 已实现的自定义 View 不想用 Compose 重写,可以直接嵌入到 Compose 中
这里以在 Compose 中嵌入 android.widget.Button 为例:
@Composable
fun AndroidViewSample() {
AndroidView(
factory = { context ->
android.widget.Button(context).apply { text = "Using android.widget.Button in Compose" }
},
)
}