三星Galaxy 7/7 Edge设备Android相机最优预览尺寸适配问题
三星Galaxy S7/S7 Edge相机横屏预览异常的解决方案
嘿,这个问题我之前做相机应用的时候刚好碰到过!你的核心代码逻辑在绝大多数设备上是没问题的,问题出在三星S7和S7 Edge这两款机型的相机系统有特殊的处理逻辑,需要针对性调整。
问题根源
三星S7系列的相机传感器在横屏模式下,系统对预览尺寸的映射逻辑和常规Android设备不一样:
- 竖屏时,系统的传感器方向和预览方向的映射符合标准逻辑,所以你的代码能正常匹配最优尺寸;
- 横屏时,三星的相机服务会强制优先使用某些特定的预览尺寸,或者没有正确处理预览尺寸和显示控件(SurfaceView/TextureView)的宽高比适配,导致画面被过度缩放甚至超出屏幕。
具体解决步骤
1. 先识别目标设备
首先要在代码里判断当前设备是不是S7/S7 Edge,用Build类获取型号即可:
private boolean isGalaxyS7Series() { String model = Build.MODEL.toLowerCase(); // SM-G930是S7,SM-G935是S7 Edge return model.contains("sm-g930") || model.contains("sm-g935"); }
2. 调整预览尺寸选择逻辑
对于这两款设备,横屏时不要单纯按屏幕宽高比从高到低选尺寸,而是优先选择和屏幕横屏宽高比一致(16:9)、分辨率略低于屏幕原生分辨率的尺寸(比如1920x1080或者1280x720)。
举个例子,修改你的最优尺寸选择方法:
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) { final double ASPECT_TOLERANCE = 0.1; double targetRatio = (double) w / h; if (sizes == null) return null; Camera.Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = h; // 针对三星S7系列横屏场景,强制锁定16:9比例 if (isGalaxyS7Series() && w > h) { targetRatio = 16.0 / 9.0; } // 遍历所有可用尺寸,找到最匹配的 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; }
3. 修正相机预览方向
三星S7系列横屏时的预览方向映射也有特殊情况,需要调整setDisplayOrientation的逻辑:
public void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId, info); int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); int degrees = 0; switch (rotation) { 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; } int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; } else { result = (info.orientation - degrees + 360) % 360; } // 针对S7系列横屏场景额外修正方向 if (isGalaxyS7Series() && rotation == Surface.ROTATION_90) { result = (result + 180) % 360; } camera.setDisplayOrientation(result); }
4. 确保显示控件和预览尺寸比例一致
最后,动态调整SurfaceView/TextureView的宽高,让它的比例和选中的预览尺寸完全一致,避免系统自动拉伸:
private void adjustPreviewViewSize(Camera.Size previewSize) { SurfaceView previewView = findViewById(R.id.camera_preview); float previewRatio = (float) previewSize.width / previewSize.height; DisplayMetrics metrics = getResources().getDisplayMetrics(); float screenRatio = (float) metrics.widthPixels / metrics.heightPixels; ViewGroup.LayoutParams params = previewView.getLayoutParams(); if (previewRatio > screenRatio) { params.width = metrics.widthPixels; params.height = (int) (params.width / previewRatio); } else { params.height = metrics.heightPixels; params.width = (int) (params.height * previewRatio); } previewView.setLayoutParams(params); }
总结
你的原始代码逻辑是通用且正确的,只是三星S7系列的相机系统有自己的特殊处理逻辑,导致横屏预览适配异常。按照上面的步骤修改后,应该就能解决画面缩放超出屏幕的问题了。
内容的提问来源于stack exchange,提问作者Lalit Agarwal
相关产品推荐
相关产品推荐

