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

三星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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:49:14