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

Android:getSupportedPreviewSizes仅返回横屏尺寸,如何获取竖屏尺寸?

解决竖屏相机预览拉伸问题:关于Camera.getSupportedPreviewSizes的说明

首先明确:Android旧Camera API(android.hardware.Camera)返回的所有预览尺寸都是横屏规格(宽>高),这是因为相机硬件传感器本身是横屏设计的,不存在所谓的「竖屏尺寸」返回。你遇到的拉伸问题,核心是没有正确处理竖屏场景下的预览比例匹配与画面旋转逻辑。

问题根源分析

你的adaptPreviewResolution方法中,比例匹配逻辑存在偏差:竖屏场景下目标尺寸是width < height,你计算的目标比例是width/height(小于1的数值),却去对比相机尺寸的height/width(同样小于1),这相当于用反向比例去匹配,很容易选到比例不匹配的尺寸,导致画面拉伸。

正确解决方案

1. 修正预览尺寸适配逻辑

竖屏场景下,我们需要将目标的竖屏比例(height/width),与相机支持的**横屏比例(width/height)**做匹配,因为相机的横屏比例对应竖屏时的有效画面比例。修改后的适配方法如下:

private Camera.Size adaptPreviewResolution(int targetVerticalWidth, int targetVerticalHeight) {
    // 竖屏的目标比例:高/宽
    float targetAspectRatio = (float) targetVerticalHeight / targetVerticalWidth;
    float minRatioDiff = Float.MAX_VALUE;
    Camera.Size bestMatchSize = null;

    for (Camera.Size size : mCamera.getParameters().getSupportedPreviewSizes()) {
        // 相机尺寸是横屏,比例为 宽/高
        float cameraAspectRatio = (float) size.width / size.height;
        float currentDiff = Math.abs(cameraAspectRatio - targetAspectRatio);

        if (currentDiff < minRatioDiff) {
            minRatioDiff = currentDiff;
            bestMatchSize = size;
        }
        // 找到完全匹配的比例,直接返回
        if (currentDiff == 0) {
            return size;
        }
    }

    return bestMatchSize;
}

2. 处理竖屏预览的画面旋转

仅匹配比例还不够,需要让相机预览画面旋转到竖屏方向,否则画面会是横屏的。在设置完预览尺寸后,添加旋转逻辑:

public int[] setPreviewResolution(int width, int height) {                
    mCamera = openCamera();
    
    // 适配竖屏对应的横屏预览尺寸
    Camera.Size matchedSize = adaptPreviewResolution(width, height);
    if (matchedSize != null) {
        mPreviewWidth = matchedSize.width;
        mPreviewHeight = matchedSize.height;
    } else {
        //  fallback到默认尺寸
        mPreviewWidth = width;
        mPreviewHeight = height;
    }

    // 设置SurfaceHolder为竖屏目标尺寸
    getHolder().setFixedSize(width, height);
    
    // 设置相机预览尺寸(横屏规格)
    Camera.Parameters params = mCamera.getParameters();
    params.setPreviewSize(mPreviewWidth, mPreviewHeight);
    mCamera.setParameters(params);

    // 计算并设置相机显示旋转角度,适配竖屏
    int displayRotation = getWindowManager().getDefaultDisplay().getRotation();
    int degrees = 0;
    switch (displayRotation) {
        case Surface.ROTATION_0: degrees = 0; break;
        case Surface.ROTATION_90: degrees = 90; break;
        case Surface.ROTATION_180: degrees = 180; break;
        case Surface.ROTATION_270: degrees = 270; break;
    }
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
    int totalRotation = (info.orientation - degrees + 360) % 360;
    mCamera.setDisplayOrientation(totalRotation);

    mGLPreviewBuffer = ByteBuffer.allocate(mPreviewWidth * mPreviewHeight * 4);
    // 输入比例统一用横屏的宽/高
    mInputAspectRatio = (float) mPreviewWidth / mPreviewHeight;

    return new int[] { width, height };
}

3. 关键注意点

  • 永远不要期望getSupportedPreviewSizes()返回竖屏尺寸,这是API的设计规则,所有预览尺寸都是基于传感器横屏的。
  • SurfaceHolder的尺寸要设置为竖屏的目标宽高,而相机预览尺寸用匹配到的横屏尺寸,两者通过旋转实现适配。
  • 不同设备的相机传感器方向可能不同,必须通过CameraInfo.orientation计算正确的旋转角度,避免画面倒置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:01:51