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
相关产品推荐
相关产品推荐

