Currently there's no equivalent to CameraView (and PreviewView) in Compose. Is it possible to wrap it and display it in a compose layout?

推荐答案

At the moment there isn't any official Composable function for CameraX so we have to inflate the legacy android view inside compose.

要实现这一目标 我们可以使用AndroidView个组合函数, 它接受两个参数

  • @param resId The id of the layout resource to be inflated.
  • @param postInflationCallback布局后要调用的回调 充气了.

and to access the lifecycle and context we use the ambients

val lifecycleOwner = LifecycleOwnerAmbient.current
val context = ContextAmbient.current

As we have everything we need let's do it:

创建布局camera_host.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.camera.view.PreviewView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/previewView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

并使用AndroidView组合功能对其进行充气.

@Composable
fun SimpleCameraPreview() {
    val lifecycleOwner = LifecycleOwnerAmbient.current
    val context = ContextAmbient.current
    val cameraProviderFuture = remember { ProcessCameraProvider.getInstance(context) }
    AndroidView(resId = R.layout.camera_host) { inflatedLayout ->
       //You can call
      // findViewById<>() and etc ... on inflatedLayout
      // here PreviewView is the root of my layout so I just cast it to
      // the PreviewView and no findViewById is required

        cameraProviderFuture.addListener(Runnable {
            val cameraProvider = cameraProviderFuture.get()
            bindPreview(
                 lifecycleOwner,
                 inflatedLayout as PreviewView /*the inflated layout*/,
                 cameraProvider)
        }, ContextCompat.getMainExecutor(context))

    }
}

fun bindPreview(
    lifecycleOwner: LifecycleOwner,
    previewView: PreviewView,
    cameraProvider: ProcessCameraProvider
) {
    var preview: Preview = Preview.Builder().build()

    var cameraSelector: CameraSelector = CameraSelector.Builder()
        .requireLensFacing(CameraSelector.LENS_FACING_BACK)
        .build()

    preview.setSurfaceProvider(previewView.createSurfaceProvider())

    var camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview)
}
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            SimpleCameraPreview()
        }
    }
}

Kotlin相关问答推荐

了解Kotlin函数

在Kotlin Jetpack中重用下拉菜单

Jetpack Compose中的数字 Select 器问题

为什么Kotlin函数参数名会 destruct 方法调用?

Kotlin 基于参数类型的返回类型推断

Android Jetpack Compose:在空的 Compose 活动中找不到 OutlinedTextField (Material3)

判断 Kotlin 变量是否为函数

根据字符串值动态过滤数组列表 - kotlin

Kotlin 使用委托进行隐式覆盖

添加 Kapt 插件后 - 执行 org.jetbrains.kotlin.gradle.internal.KaptExecution 时发生故障

Kotlin 可打包类抛出 ClassNotFoundException

如何使用 Android CameraX 自动对焦

如何在 IntelliJ 中更改 Kotlin 的this property has a backing field代码编辑器突出显示?

对列表中数字的子集求和

Android Room - error: Cannot figure out how to save this field into database

如何在 Spring WebFlux 的响应正文中流式传输二进制数据

Kotlin:具有多个不同类型设置器的单个属性

将字符串编码为Kotlin中的UTF-8

使用 java lambda 调用 kotlin 函数时,Kotlin 无法访问 kotlin.jvm.functions.Function1

Kotlin:获取文件的扩展名,例如.txt