相机与媒体 (Camera & Media)
Compose 目前没有原生的 Camera 或 Video 组件,我们需要通过 AndroidView 来桥接 Android 原生的 CameraX 和 ExoPlayer。
1. 相机预览 (CameraX)
依赖
kotlin
val camerax_version = "1.3.1"
implementation("androidx.camera:camera-core:${camerax_version}")
implementation("androidx.camera:camera-camera2:${camerax_version}")
implementation("androidx.camera:camera-lifecycle:${camerax_version}")
implementation("androidx.camera:camera-view:${camerax_version}")实现 CameraPreview
kotlin
@Composable
fun CameraPreview(
modifier: Modifier = Modifier,
scaleType: PreviewView.ScaleType = PreviewView.ScaleType.FILL_CENTER,
cameraSelector: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
) {
val lifecycleOwner = LocalLifecycleOwner.current
AndroidView(
modifier = modifier,
factory = { context ->
val previewView = PreviewView(context).apply {
this.scaleType = scaleType
}
// 获取 CameraProvider
val cameraProviderFuture = ProcessCameraProvider.getInstance(context)
cameraProviderFuture.addListener({
val cameraProvider = cameraProviderFuture.get()
// 创建 Preview 用例
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
try {
// 解绑所有并重新绑定
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector,
preview
)
} catch (e: Exception) {
Log.e("CameraPreview", "Use case binding failed", e)
}
}, ContextCompat.getMainExecutor(context))
previewView
}
)
}2. 视频播放 (ExoPlayer)
依赖
kotlin
implementation("androidx.media3:media3-exoplayer:1.2.0")
implementation("androidx.media3:media3-ui:1.2.0")实现 VideoPlayer
kotlin
@Composable
fun VideoPlayer(uri: Uri) {
val context = LocalContext.current
// 初始化 ExoPlayer
val exoPlayer = remember {
ExoPlayer.Builder(context).build().apply {
setMediaItem(MediaItem.fromUri(uri))
prepare()
playWhenReady = true
}
}
// 记得在组件销毁时释放 Player
DisposableEffect(Unit) {
onDispose {
exoPlayer.release()
}
}
// 使用 PlayerView
AndroidView(
factory = { ctx ->
PlayerView(ctx).apply {
player = exoPlayer
}
},
modifier = Modifier
.fillMaxWidth()
.aspectRatio(16f / 9f) // 保持 16:9
)
}生命周期处理
对于视频播放器,通常还需要处理 onPause (暂停播放) 和 onResume (恢复播放)。可以通过监听 LocalLifecycleOwner 来实现。