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

如何通过编程将显示方向从横向改为纵向并同步旋转相机视图?

动态切换显示方向 + 相机画面同步旋转实现方案

以下分Android、iOS两个主流移动平台给出具体实现代码:

Android 平台

1. 动态切换屏幕显示方向

直接调用Activity的setRequestedOrientation方法,传入对应的方向常量即可:

// 切换为纵向(竖屏)
requestedOrientation = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT

// 切换为横向(横屏)
requestedOrientation = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE

// 恢复跟随系统自动旋转
requestedOrientation = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR

2. 相机画面同步旋转

推荐使用Google官方的CameraX库(Jetpack组件,兼容性更好),核心是根据屏幕旋转角度设置相机预览的目标旋转值:

import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.content.ContextCompat
import android.view.Surface

// 初始化CameraX预览
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
    val cameraProvider = cameraProviderFuture.get()
    val previewView = findViewById<androidx.camera.view.PreviewView>(R.id.previewView)
    
    val preview = Preview.Builder().build().also {
        it.setSurfaceProvider(previewView.surfaceProvider)
    }

    // 获取当前屏幕旋转角度
    val screenRotation = previewView.display.rotation
    // 转换为相机需要的旋转角度
    val targetRotation = when(screenRotation) {
        Surface.ROTATION_0 -> 0
        Surface.ROTATION_90 -> 90
        Surface.ROTATION_180 -> 180
        Surface.ROTATION_270 -> 270
        else -> 0
    }
    // 同步预览方向
    preview.targetRotation = targetRotation

    try {
        cameraProvider.unbindAll()
        cameraProvider.bindToLifecycle(this, CameraSelector.DEFAULT_BACK_CAMERA, preview)
    } catch(e: Exception) {
        e.printStackTrace()
    }
}, ContextCompat.getMainExecutor(this))

如果使用旧版Camera API,需调用Camera.setDisplayOrientation方法调整:

import android.hardware.Camera;
import android.view.Surface;

Camera camera = Camera.open();
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(0, cameraInfo);

// 获取屏幕旋转角度
int rotation = 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 (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
    result = (cameraInfo.orientation + degrees) % 360;
    result = (360 - result) % 360; // 前置摄像头需镜像处理
} else {
    result = (cameraInfo.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);

iOS 平台

1. 动态切换屏幕显示方向

通过修改UIDevice的orientation属性强制切换,同时确保ViewController支持对应方向:

// 切换为纵向
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")

// 切换为横向(左侧横屏)
UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")

在ViewController中声明支持的方向:

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    // 根据需求返回,比如.portrait、.landscape或.all
    return .portrait
}

2. 相机画面同步旋转

使用AVFoundation框架,在屏幕旋转时更新预览层的videoOrientation属性:

import AVFoundation
import UIKit

class CameraVC: UIViewController {
    private var captureSession: AVCaptureSession?
    private var previewLayer: AVCaptureVideoPreviewLayer?

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        // 屏幕旋转时同步相机预览方向
        updateCameraPreviewOrientation()
    }

    private func updateCameraPreviewOrientation() {
        guard let connection = previewLayer?.connection, connection.isVideoOrientationSupported else {
            return
        }

        let deviceOrientation = UIDevice.current.orientation
        let videoOrientation: AVCaptureVideoOrientation
        switch deviceOrientation {
        case .portrait:
            videoOrientation = .portrait
        case .portraitUpsideDown:
            videoOrientation = .portraitUpsideDown
        case .landscapeLeft:
            videoOrientation = .landscapeRight
        case .landscapeRight:
            videoOrientation = .landscapeLeft
        default:
            videoOrientation = .portrait
        }
        connection.videoOrientation = videoOrientation
    }

    // 初始化相机预览示例
    private func setupCamera() {
        captureSession = AVCaptureSession()
        captureSession?.sessionPreset = .high

        guard let backCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back),
              let input = try? AVCaptureDeviceInput(device: backCamera),
              captureSession?.canAddInput(input) == true else {
            return
        }

        captureSession?.addInput(input)
        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession!)
        previewLayer?.frame = view.bounds
        previewLayer?.videoGravity = .resizeAspectFill
        view.layer.addSublayer(previewLayer!)

        // 初始设置预览方向
        updateCameraPreviewOrientation()
        captureSession?.startRunning()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 22:17:18