ITmob-Ly
发布于 2023-07-10 / 334 阅读
0

Jetpack Compose 和 Android View 的互相操作

将整个项目迁移到 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。

  1. 在布局中加一个 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>
    
  2. 获得 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" },
                )
            },
        )
    }
}

Add ComposeView in Android View

Compose 中嵌入 View

Jetpack Compose 是独立于传统的 Android View 系统,但在 Compose 中可以也使用 View(及 android.view.View 的子类)。

为什么要在 Compose 中使用 Android View:

  1. WebView,AdView 等还没有原生的 Compose 版本
  2. 已实现的自定义 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" }
        },
    )
}

Add AndroidView in Composable function