Android CameraX如何设置相机捕获比例并实现全屏显示?
解决CameraX预览无法全屏显示的问题
针对你遇到的CameraX预览无法全屏的问题,核心问题出在PreviewView的缩放类型和分辨率策略的匹配逻辑上,以下是具体的修复步骤:
1. 修改PreviewView的缩放类型
你当前设置的FIT_CENTER会让相机画面按原始比例居中显示,无法填充整个PreviewView,导致出现黑边。需要将其改为填充模式:
previewView.scaleType = PreviewView.ScaleType.FILL_START
FILL_START会让画面填充整个PreviewView(可能会裁剪部分画面),如果需要保持画面居中裁剪,可以改用FILL_CENTER。
2. 让分辨率策略匹配PreviewView的宽高比
固定设置1280×1280的分辨率可能和PreviewView的实际宽高比不匹配,且相机硬件可能不支持该比例,导致CameraX自动回退到其他分辨率。正确的做法是优先匹配PreviewView的比例:
步骤2.1 确保获取到PreviewView的实际宽高
由于View初始化时可能还未完成测量,直接获取宽高会得到0,需要监听View的布局完成事件后再初始化相机:
// 在初始化CameraManager的地方添加监听 previewView.addOnLayoutChangeListener(object : View.OnLayoutChangeListener { override fun onLayoutChange( v: View?, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int ) { if (previewView.width > 0 && previewView.height > 0) { startCamera() previewView.removeOnLayoutChangeListener(this) // 只执行一次 } } })
步骤2.2 调整ResolutionSelector的配置
在startCamera()方法中,根据PreviewView的实际宽高比构建分辨率选择器,优先匹配该比例的分辨率:
fun startCamera() { previewView.scaleType = PreviewView.ScaleType.FILL_START // 获取PreviewView的宽高比 val previewRatio = Rational(previewView.width, previewView.height) val resolutionSelector = ResolutionSelector.Builder() // 优先选择与PreviewView比例匹配的分辨率 .setAspectRatioStrategy( AspectRatioStrategy( previewRatio, AspectRatioStrategy.FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER ) ) // 如果需要限制分辨率范围,可以添加以下配置(可选) // .setResolutionStrategy( // ResolutionStrategy( // Size(1920, 1080), // 目标分辨率,根据需求调整 // ResolutionStrategy.FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER // ) // ) .build() val cameraProviderFuture = ProcessCameraProvider.getInstance(context) cameraProviderFuture.addListener({ val cameraProvider = cameraProviderFuture.get() preview = Preview.Builder() .setResolutionSelector(resolutionSelector) .build() // 让ImageAnalysis也使用相同的分辨率选择器,避免多UseCases冲突 imageAnalysis = ImageAnalysis.Builder() .setResolutionSelector(resolutionSelector) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build() .also { it.setAnalyzer(cameraExecutor, qrCodeProcessor) } val cameraSelector = CameraSelector.Builder() .requireLensFacing(cameraSelectorOption) .build() imageCapture = ImageCapture.Builder() .setResolutionSelector(resolutionSelector) .build() setCameraConfig(cameraProvider, cameraSelector) }, ContextCompat.getMainExecutor(context)) }
3. 统一所有UseCases的分辨率策略
确保Preview、ImageAnalysis、ImageCapture三个UseCases使用相同的ResolutionSelector,CameraX会自动选择一个所有UseCases都支持的最优分辨率,避免因分辨率要求不一致导致的显示异常。
额外注意事项
- 相机硬件支持的分辨率是有限的,如果强制设置一个硬件不支持的比例或分辨率,CameraX会自动回退到最近的支持选项,这可能导致显示不符合预期。
- 如果需要完全无裁剪的全屏显示,需要确保相机输出的分辨率比例和PreviewView的比例完全一致,否则只能通过裁剪或拉伸来填充(拉伸会导致画面变形,不推荐)。
内容的提问来源于stack exchange,提问作者Louis Berthier
相关产品推荐
相关产品推荐

