Jetpack Compose实现正方形相机预览时出现比例异常及UI重叠问题求助
Jetpack Compose实现正方形相机预览时出现比例异常及UI重叠问题求助
大家好,我目前在基于Jetpack Compose开发相机相关功能,需求是只使用传感器采集的图像中的正方形区域,所以希望在UI里显示正方形的相机预览,其他UI元素都放在预览区域之外。但实际运行后遇到了两个问题:
- 预览区域显示为3:4的矩形,不是预期的正方形
- 预览区域和下方的UI元素重叠了,而这些UI是按照正方形预览的布局逻辑来排列的
我尝试了以下代码,麻烦大家帮忙看看问题出在哪里:
MainActivity代码
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { MyApplicationTheme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> Content( modifier = Modifier.padding(innerPadding) ) } } } } }
CameraPreview Composable
@Composable fun CameraPreview() { val previewH = (LocalConfiguration.current.screenWidthDp).dp fun startCamera(context: Context, previewView: PreviewView) { val cameraProviderFuture = ProcessCameraProvider.getInstance(context) cameraProviderFuture.addListener({ val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get() // CameraSelector for back camera val cameraSelector = CameraSelector.Builder() .requireLensFacing(CameraSelector.LENS_FACING_BACK) .build() // Set up Preview use case val preview = Preview.Builder().build().also { it.surfaceProvider = previewView.surfaceProvider } try { // Unbind all use cases before rebinding cameraProvider.unbindAll() val viewPort = ViewPort.Builder(Rational(1,1), Surface.ROTATION_0) .setScaleType(ViewPort.FILL_CENTER) .build() val useGrp = UseCaseGroup.Builder() .addUseCase(preview) .addUseCase(ImageAnalysis.Builder().build()) .setViewPort(viewPort) .build() // Bind the camera to the lifecycle and the Preview use case cameraProvider.bindToLifecycle(context as LifecycleOwner, cameraSelector, useGrp) } catch (exc: Exception) { Log.e("CameraXApp", "Use case binding failed", exc) } }, ContextCompat.getMainExecutor(context)) } Box(modifier = Modifier.fillMaxWidth().height(previewH)) { AndroidView( modifier = Modifier.fillMaxSize() .onGloballyPositioned { c -> Log.i("PREVIEW", "Androview size: ${c.size}") }, factory = { context -> val screenWidth = Resources.getSystem().displayMetrics.widthPixels val previewView = PreviewView(context).apply { scaleType = PreviewView.ScaleType.FILL_CENTER layoutParams = ViewGroup.LayoutParams( screenWidth, screenWidth ) } //focusFactory = previewView.meteringPointFactory startCamera(context, previewView) previewView } ) } }
Content Composable
@Composable fun Content(modifier: Modifier = Modifier) { val ctx = LocalContext.current val needPermission = remember { mutableStateOf(ContextCompat.checkSelfPermission(ctx, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) } val CAMERA_PERMISSION_REQUEST_CODE = 101 @Composable fun PermissionRequestUI() { Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text("Camera permission is required to use this feature.") Button(onClick = { ActivityCompat.requestPermissions( ctx as Activity, arrayOf(Manifest.permission.CAMERA), CAMERA_PERMISSION_REQUEST_CODE ) needPermission.value = false }) { Text("Grant Permission") } } } if(needPermission.value) { PermissionRequestUI() } else { Column(modifier = modifier) { CameraPreview() Text("ABYR") Text("VALG") Text("qwert") Text("zxcv") } } }
我已经尝试设置了ViewPort的比例为1:1,也把PreviewView的宽高都设为屏幕宽度,外层的Box高度也设置成了屏幕宽度的dp值,但还是没解决问题,希望大家能帮我找到问题所在,谢谢!
内容来源于stack exchange
相关产品推荐
相关产品推荐

