为何Camera2支持的预览尺寸宽度总是大于高度?
解决Camera2 API预览尺寸宽高与屏幕方向不匹配的问题
我太懂你在Camera2项目里碰到的这个别扭点了——通过StreamConfigurationMap.getOutputSizes(SurfaceTexture.class)拿到的预览尺寸,不管怎么看都是宽大于高,但你用getResources().getDisplayMetrics()查屏幕宽高时,总觉得两者对不上对吧?这其实是Camera2 API的设计特性,我来给你捋清楚:
为什么预览尺寸总是宽>高?
相机传感器本身是横向原生设计的,它输出的所有原始尺寸都是以横向为基准(比如常见的1920×1080,宽1920、高1080),和你的手机当前是竖屏还是横屏完全无关。而getDisplayMetrics()拿到的屏幕尺寸,是基于设备当前物理方向的——比如竖屏状态下,屏幕的宽度是较短的那个数值,高度是较长的,但相机的输出方向和这个是独立的两个维度。
怎么让预览尺寸匹配屏幕方向?
你需要根据当前屏幕的旋转角度,对相机输出的尺寸做对应调整,步骤如下:
- 获取当前屏幕旋转角度:
int rotation = getWindowManager().getDefaultDisplay().getRotation(); - 根据旋转角度匹配宽高比:
- 竖屏状态(旋转角度为
Surface.ROTATION_0或Surface.ROTATION_180):需要把相机尺寸的宽高互换,来适配竖屏的宽高比例 - 横屏状态(旋转角度为
Surface.ROTATION_90或Surface.ROTATION_270):直接使用相机的原始尺寸比例即可
- 竖屏状态(旋转角度为
- 筛选最优预览尺寸:
遍历相机返回的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
相关产品推荐
相关产品推荐

