You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用内置相机拍照自动裁剪且预览尺寸偏小问题排查

解决相机预览界面偏小、拍摄照片自动裁剪的问题

嘿,我来帮你捋捋这个问题——你遇到的预览界面比常规相机小、拍出来的照片自动被裁剪的情况,核心原因基本都是预览尺寸、拍照分辨率和承载预览的SurfaceView尺寸三者的比例不匹配导致的。结合你给出的surfaceChanged代码片段,咱们具体分析:

为啥会出现这种情况?

1. 预览尺寸选得不对

你代码里直接用了mPreviewSize来设置预览分辨率,但如果这个尺寸不是相机硬件原生支持的预览尺寸,或者和相机的拍照分辨率比例不一致,就会触发系统的强制适配:

  • 预览画面被拉伸/压缩,看起来比正常相机预览小
  • 拍摄时相机按照自身支持的拍照分辨率输出,因为和预览比例不匹配,最终照片会被自动裁剪来对齐比例

2. SurfaceView和预览尺寸比例不兼容

如果你的SurfaceView(显示预览的视图)宽高比,和你设置的预览尺寸宽高比不一样,系统会自动裁剪预览画面来适配视图,这也会让预览看起来偏小,同时拍摄的照片因为遵循相机的拍照比例,自然也会被裁剪。

怎么修复?

第一步:先拿到相机支持的合法尺寸

首先要遍历相机支持的所有预览和拍照尺寸,找到比例一致的最佳配对,避免用不兼容的尺寸:

private Camera.Size getOptimalSize(List<Camera.Size> sizes, int targetWidth, int targetHeight) {
    final double ASPECT_TOLERANCE = 0.1; // 比例误差容忍度
    double targetRatio = (double) targetHeight / targetWidth;
    // 注意:相机的尺寸是按横屏定义的,所以要对应屏幕的高宽比

    if (sizes == null) return null;

    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    // 优先找比例匹配且尺寸最接近目标的
    for (Camera.Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }

    // 如果没找到比例匹配的,就选尺寸最接近的
    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Camera.Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

第二步:在surfaceChanged里正确设置参数

确保预览尺寸和拍照尺寸的比例完全一致,同时适配SurfaceView的尺寸:

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    if (mCamera == null) return;

    try {
        Camera.Parameters parameters = mCamera.getParameters();
        
        // 获取适配当前SurfaceView的最佳预览尺寸
        List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
        Camera.Size optimalPreviewSize = getOptimalSize(previewSizes, w, h);
        
        // 获取和预览尺寸比例一致的最佳拍照尺寸
        List<Camera.Size> pictureSizes = parameters.getSupportedPictureSizes();
        Camera.Size optimalPictureSize = getOptimalSize(pictureSizes, optimalPreviewSize.width, optimalPreviewSize.height);
        
        // 设置预览和拍照尺寸
        parameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
        parameters.setPictureSize(optimalPictureSize.width, optimalPictureSize.height);
        
        // 竖屏应用别忘了设置相机显示方向,不然预览会歪
        mCamera.setDisplayOrientation(90);
        parameters.setRotation(90);
        
        mCamera.setParameters(parameters);
        mCamera.startPreview();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

第三步:让SurfaceView适配预览比例

别给SurfaceView设固定宽高,要么用布局权重让它自适应,要么在代码里动态调整宽高,保证和预览尺寸的比例一致:

<SurfaceView
    android:id="@+id/camera_preview"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

简单来说,只要让预览尺寸、拍照尺寸、SurfaceView尺寸三者的宽高比完全对齐,就能解决预览偏小和照片被裁剪的问题啦。

内容的提问来源于stack exchange,提问作者Oktawian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:12:58