如何通过编程将显示方向从横向改为纵向并同步旋转相机视图?
动态切换显示方向 + 相机画面同步旋转实现方案
以下分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
相关产品推荐
相关产品推荐

