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

Camera2 API竖屏预览拉伸问题求助(三星Android9已试多方案无效)

Hey there, let's tackle this stubborn Samsung Android 9 Camera2 preview stretching issue in portrait mode. I’ve dealt with similar device-specific quirks before, so here are targeted fixes that should work:

解决方案1:针对三星设备修正SurfaceTexture变换矩阵

Samsung's Android 9 ROM has a unique quirk in how it calculates TextureView transformation matrices for portrait mode. Skip the default AutoFitTextureView logic and manually adjust the matrix with these steps:

  • In the onSurfaceTextureAvailable callback, fetch camera sensor orientation and your selected preview size first:
    CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
    int sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
    Size previewSize = // Your chosen optimal preview size
    
  • Calculate the correct scale and apply the matrix with Samsung-specific adjustments:
    float ratio;
    int viewWidth = textureView.getWidth();
    int viewHeight = textureView.getHeight();
    Configuration config = getResources().getConfiguration();
    
    if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
        // Swap width/height ratio for Samsung's portrait handling
        ratio = (float) previewSize.getHeight() / previewSize.getWidth();
        float scaleX, scaleY;
        
        if (sensorOrientation == 90 || sensorOrientation == 270) {
            scaleX = ratio;
            scaleY = 1.0f;
            // Adjust scale to fit view without stretching
            if (scaleX * viewWidth < viewHeight) {
                scaleX = (float) viewHeight / viewWidth / ratio;
            } else {
                scaleY = (float) viewWidth / viewHeight * ratio;
            }
        } else {
            scaleX = 1.0f;
            scaleY = ratio;
            if (scaleY * viewHeight < viewWidth) {
                scaleY = (float) viewWidth / viewHeight / ratio;
            } else {
                scaleX = (float) viewHeight / viewWidth * ratio;
            }
        }
        
        // Apply transformation matrix with rotation and center alignment
        Matrix matrix = new Matrix();
        matrix.setScale(scaleX, scaleY);
        matrix.postRotate(90); // Match portrait orientation
        float centerX = viewWidth / 2f;
        float centerY = viewHeight / 2f;
        matrix.postTranslate(
            (viewWidth - previewSize.getHeight() * scaleX) / 2,
            (viewHeight - previewSize.getWidth() * scaleY) / 2
        );
        textureView.setTransform(matrix);
    }
    
解决方案2:强制选择与屏幕比例完全匹配的预览尺寸

Some Samsung devices force stretching instead of cropping when preview size aspect ratio doesn't match the screen. Filter supported sizes to find an exact match:

  • Use this method to pick the optimal size:
    private Size chooseOptimalSize(Size[] choices, int viewWidth, int viewHeight) {
        List<Size> exactMatches = new ArrayList<>();
        float targetRatio;
        Configuration config = getResources().getConfiguration();
        
        // Adjust target ratio for portrait mode
        if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
            targetRatio = (float) viewHeight / viewWidth;
        } else {
            targetRatio = (float) viewWidth / viewHeight;
        }
        
        // Find sizes with exact aspect ratio match
        for (Size size : choices) {
            float sizeRatio = (float) size.getWidth() / size.getHeight();
            if (Math.abs(sizeRatio - targetRatio) < 0.001f) {
                exactMatches.add(size);
            }
        }
        
        // Pick the largest exact match for best resolution
        if (!exactMatches.isEmpty()) {
            return Collections.max(exactMatches, (a, b) -> Long.compare(
                (long) a.getWidth() * a.getHeight(),
                (long) b.getWidth() * b.getHeight()
            ));
        }
        
        // Fallback to closest match if no exact fit
        Size bestFit = choices[0];
        float smallestDiff = Float.MAX_VALUE;
        for (Size size : choices) {
            float sizeRatio = (float) size.getWidth() / size.getHeight();
            float diff = Math.abs(sizeRatio - targetRatio);
            if (diff < smallestDiff) {
                smallestDiff = diff;
                bestFit = size;
            }
        }
        return bestFit;
    }
    
  • Important: Pass the actual measured width/height of your TextureView (not the full screen resolution) to account for status/navigation bars.
解决方案3:禁用TextureView硬件加速(应急修复)

If the above fixes fail, some Samsung Android 9 builds have bugs with TextureView hardware acceleration. Try disabling it:

  • In your layout XML:
    <AutoFitTextureView
        android:id="@+id/textureView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:hardwareAccelerated="false" />
    
  • Or programmatically:
    textureView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    

Note: This may reduce preview performance, so only use it as a last resort.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 09:02:47