You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android竖屏模式下Google Vision Camera Source预览边距及对焦拉伸问题

解决Google Vision API条码扫描的边距与旋转拉伸问题

看起来你遇到了Camera预览布局和旋转适配的常见坑,我来帮你拆解问题并给出具体的修复方案:

问题根源分析

  1. 右侧边距match_parent只是让View占满父容器,但CameraSource默认的预览尺寸和你的屏幕宽高比不匹配,导致预览画面没有填满View,从而出现侧边距。
  2. 旋转后拉伸变形:屏幕旋转时,没有重新计算适配当前屏幕比例的最佳预览尺寸,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

火山引擎 最新活动