Android竖屏模式下Google Vision Camera Source预览边距及对焦拉伸问题
解决Google Vision API条码扫描的边距与旋转拉伸问题
看起来你遇到了Camera预览布局和旋转适配的常见坑,我来帮你拆解问题并给出具体的修复方案:
问题根源分析
- 右侧边距:
match_parent只是让View占满父容器,但CameraSource默认的预览尺寸和你的屏幕宽高比不匹配,导致预览画面没有填满View,从而出现侧边距。 - 旋转后拉伸变形:屏幕旋转时,没有重新计算适配当前屏幕比例的最佳预览尺寸,Camera仍然用之前的尺寸渲染,就会导致拉伸。
具体修复步骤
1. 修复CameraSourcePreview的测量逻辑
默认的CameraSourcePreview可能没有正确处理预览尺寸的比例适配,你需要重写onMeasure方法,让View按照Camera的最佳预览比例来调整大小,而不是强制填满屏幕:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mCameraSource == null) { return; } Size size = mCameraSource.getPreviewSize(); if (size == null) { return; } // 交换宽高,因为Camera的预览尺寸是基于自然方向(横屏)的 int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); int previewWidth = size.getWidth(); int previewHeight = size.getHeight(); // 计算预览比例和View比例,调整View的测量尺寸 float viewRatio = (float) width / height; float previewRatio = (float) previewWidth / previewHeight; if (viewRatio > previewRatio) { // View更宽,按高度适配,调整宽度 width = (int) (height * previewRatio); } else { // View更高,按宽度适配,调整高度 height = (int) (width / previewRatio); } setMeasuredDimension(width, height); }
2. 处理屏幕旋转,重新初始化CameraSource
在你的扫描Activity中,重写onConfigurationChanged方法,当屏幕旋转时,释放旧的CameraSource并重新创建,确保预览尺寸适配新的屏幕方向:
@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // 释放旧的CameraSource if (mCameraSource != null) { mCameraSource.stop(); mCameraSource.release(); mCameraSource = null; } // 重新初始化CameraSource和预览 startCameraSource(); // 这个方法是你原来初始化CameraSource并绑定到Preview的逻辑 }
注意:要在AndroidManifest.xml中给你的Activity添加android:configChanges="orientation|screenSize"属性,避免旋转时Activity重启。
3. 确保Overlay的扫描区域绘制正确
你的扫描Overlay需要基于最终测量后的Preview尺寸来计算扫描框的位置,而不是直接用屏幕尺寸。在Overlay的onDraw方法中,先获取Preview的实际宽高:
@Override public void onDraw(Canvas canvas) { super.onDraw(canvas); // 获取Preview的实际尺寸 int previewWidth = getWidth(); int previewHeight = getHeight(); // 计算扫描框的位置(比如居中的方形) int scanSize = Math.min(previewWidth, previewHeight) / 2; int left = (previewWidth - scanSize) / 2; int top = (previewHeight - scanSize) / 2; int right = left + scanSize; int bottom = top + scanSize; // 绘制扫描框 canvas.drawRect(left, top, right, bottom, mScanPaint); }
额外建议
- 初始化CameraSource时,不要直接用默认的预览尺寸,而是调用
setRequestedPreviewSize指定和屏幕比例接近的尺寸,或者让CameraSource自动选择最佳尺寸:
mCameraSource = new CameraSource.Builder(context, barcodeDetector) .setFacing(CameraSource.CAMERA_FACING_BACK) .setRequestedPreviewSize(1920, 1080) // 选择和屏幕比例一致的尺寸 .setAutoFocusEnabled(true) .build();
这样处理后,应该就能解决右侧边距和旋转拉伸的问题了。
内容的提问来源于stack exchange,提问作者Thiru




