CameraX 1.2.1结合Jetpack Compose相机预览异常求助
CameraX 1.2.1 与 Jetpack Compose 集成预览无显示问题修复
问题核心原因
- 布局层级遮挡:原代码中
Icon组件先于AndroidView渲染,且设置了fillMaxWidth()和height(IntrinsicSize.Max),完全覆盖相机预览区域,仅在返回页面时Icon随页面销毁才短暂露出预览。 - 初始化时机错误:依赖硬编码的
delay(2000)触发UI渲染,未关联权限申请结果,可能出现权限未通过就执行相机绑定的情况。 - 预览绑定逻辑不当:在
LaunchedEffect中提前绑定预览,但此时AndroidView尚未加入Compose树,SurfaceProvider关联失效。
修复后的代码
@Composable @Destination fun TakePictureScreen( viewModel: TakePictureViewModel = hiltViewModel() ) { val lensFacing = CameraSelector.LENS_FACING_FRONT val context = LocalContext.current val lifecycleOwner = LocalLifecycleOwner.current val hasCameraPermission = remember { mutableStateOf(false) } val preview = remember { Preview.Builder().build() } val imageCapture = remember { ImageCapture.Builder().build() } val cameraSelector = remember { CameraSelector.Builder() .requireLensFacing(lensFacing) .build() } val cameraPermissionResultLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.RequestPermission(), onResult = { isGranted -> hasCameraPermission.value = isGranted viewModel.onPermissionResult( permission = Manifest.permission.CAMERA, isGranted = isGranted ) } ) LaunchedEffect(Unit) { cameraPermissionResultLauncher.launch(Manifest.permission.CAMERA) } if (hasCameraPermission.value) { // 先渲染全屏预览 AndroidView( factory = { ctx -> PreviewView(ctx).apply { // View创建完成后关联SurfaceProvider并绑定相机 lifecycleScope.launch { val cameraProvider = ProcessCameraProvider.getInstance(ctx).await() cameraProvider.unbindAll() preview.setSurfaceProvider(surfaceProvider) cameraProvider.bindToLifecycle( lifecycleOwner, cameraSelector, preview, imageCapture ) } } }, modifier = Modifier.fillMaxSize() ) // 后渲染局部Icon,避免遮挡预览 Icon( tint = MaterialTheme.colors.primary, modifier = Modifier .align(Alignment.TopCenter) .padding(8.dp) .size(48.dp), painter = painterResource(R.drawable.can_location), contentDescription = stringResource(id = R.string.take_photo) ) } else { Text(text = "需要相机权限才能使用") } }
关键修改说明
- 权限驱动UI:用
hasCameraPermission替代硬编码延迟的cameraInit,确保权限通过后才渲染相机相关UI。 - 调整布局顺序:将
AndroidView放在Icon之前,且给Icon设置固定尺寸,避免覆盖全屏预览。 - 正确绑定时机:将相机绑定逻辑移至
AndroidView的factory回调中,确保PreviewView已完成创建后再关联SurfaceProvider和相机生命周期。 - 规范相机提供者获取:使用
ProcessCameraProvider.getInstance(ctx).await()异步获取相机提供者,避免阻塞主线程。
问题截图说明
- 相机功能触发前界面

- 相机运行中界面(右上角绿色标识显示相机已启动)

- 返回过渡时短暂显示的相机画面

内容的提问来源于stack exchange,提问作者trixo
相关产品推荐
相关产品推荐

