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

为何Camera2支持的预览尺寸宽度总是大于高度?

解决Camera2 API预览尺寸宽高与屏幕方向不匹配的问题

我太懂你在Camera2项目里碰到的这个别扭点了——通过StreamConfigurationMap.getOutputSizes(SurfaceTexture.class)拿到的预览尺寸,不管怎么看都是宽大于高,但你用getResources().getDisplayMetrics()查屏幕宽高时,总觉得两者对不上对吧?这其实是Camera2 API的设计特性,我来给你捋清楚:

为什么预览尺寸总是宽>高?

相机传感器本身是横向原生设计的,它输出的所有原始尺寸都是以横向为基准(比如常见的1920×1080,宽1920、高1080),和你的手机当前是竖屏还是横屏完全无关。而getDisplayMetrics()拿到的屏幕尺寸,是基于设备当前物理方向的——比如竖屏状态下,屏幕的宽度是较短的那个数值,高度是较长的,但相机的输出方向和这个是独立的两个维度。

怎么让预览尺寸匹配屏幕方向?

你需要根据当前屏幕的旋转角度,对相机输出的尺寸做对应调整,步骤如下:

  1. 获取当前屏幕旋转角度:
    int rotation = getWindowManager().getDefaultDisplay().getRotation();
    
  2. 根据旋转角度匹配宽高比:
    • 竖屏状态(旋转角度为Surface.ROTATION_0或Surface.ROTATION_180):需要把相机尺寸的宽高互换,来适配竖屏的宽高比例
    • 横屏状态(旋转角度为Surface.ROTATION_90或Surface.ROTATION_270):直接使用相机的原始尺寸比例即可
  3. 筛选最优预览尺寸:
    遍历相机返回的Size[] choices,找到和屏幕宽高比最接近、尺寸合适的选项,再根据屏幕旋转决定是否交换宽高。

给你一个简单的筛选示例:

private Size chooseOptimalSize(Size[] choices, int screenWidth, int screenHeight) {
    List<Size> matchedSizes = new ArrayList<>();
    float screenRatio = (float) screenWidth / screenHeight;

    for (Size size : choices) {
        float cameraRatio = (float) size.getWidth() / size.getHeight();
        // 竖屏时,用相机尺寸的高/宽 匹配屏幕的宽/高(因为竖屏屏幕宽<高)
        if (Math.abs(cameraRatio - 1/screenRatio) < 0.01f) { // 允许小比例误差
            matchedSizes.add(size);
        }
    }

    if (!matchedSizes.isEmpty()) {
        // 返回尺寸最小的匹配项(也可以根据需求选最大的)
        return Collections.min(matchedSizes, (lhs, rhs) -> 
            Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight())
        );
    } else {
        return choices[0];
    }
}

额外提醒

  • 设置预览Session时,别忘了在CameraCaptureSession.setRepeatingRequest()的参数里配置对应的SurfaceRotation,避免预览画面出现旋转错位
  • 如果你的App支持横竖屏切换,要在屏幕方向改变时重新获取相机尺寸并更新预览配置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:16:42