如何让AVFoundation相机画面拉伸旋转适配横向UIView
解决AVFoundation相机画面横向拉伸适配UIView的问题
要实现相机画面横向拉伸并适配你的LiveStreamView,需要从预览层的缩放模式、视频方向适配这两个核心点入手,以下是具体修改方案:
1. 完善LiveStreamView的配置
给LiveStreamView添加关联捕获会话的方法,并设置预览层的缩放与方向属性:
class LiveStreamView: UIView { override class var layerClass: AnyClass { return AVCaptureVideoPreviewLayer.self } var videoPreviewLayer: AVCaptureVideoPreviewLayer { return layer as! AVCaptureVideoPreviewLayer } // 添加关联捕获会话的方法 func setup(with session: AVCaptureSession) { videoPreviewLayer.session = session // 设置画面拉伸模式:填充整个View,保持比例但会裁剪边缘 videoPreviewLayer.videoGravity = .resizeAspectFill // 自动适配设备方向 updateVideoOrientation() } // 更新视频方向以匹配界面方向 func updateVideoOrientation() { guard let interfaceOrientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation else { return } let videoOrientation: AVCaptureVideoOrientation switch interfaceOrientation { case .portrait: videoOrientation = .portrait case .portraitUpsideDown: videoOrientation = .portraitUpsideDown case .landscapeLeft: videoOrientation = .landscapeRight case .landscapeRight: videoOrientation = .landscapeLeft default: videoOrientation = .portrait } videoPreviewLayer.connection?.videoOrientation = videoOrientation } }
2. 调整AVFoundationHandler的初始化流程
设置会话预设分辨率,并确保捕获会话正常启动:
import Foundation import AVFoundation import UIKit class AVFoundationHandler { let captureSession = AVCaptureSession() init() { configure() } func configure() { // 设置会话预设为高清分辨率,可根据需求调整 captureSession.sessionPreset = .hd1920x1080 guard let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back), let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice), captureSession.canAddInput(videoDeviceInput) else { return } captureSession.addInput(videoDeviceInput) // 启动捕获会话 captureSession.startRunning() } }
3. 在ViewController中完成关联
在视图控制器里完成AVFoundationHandler与LiveStreamView的绑定,并处理屏幕旋转时的方向更新:
class ViewController: UIViewController { let liveStreamView = LiveStreamView() let avHandler = AVFoundationHandler() override func viewDidLoad() { super.viewDidLoad() setupLiveStreamView() } override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() // 屏幕旋转时同步更新视频方向 liveStreamView.updateVideoOrientation() } private func setupLiveStreamView() { liveStreamView.frame = view.bounds liveStreamView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(liveStreamView) // 关联捕获会话到预览层 liveStreamView.setup(with: avHandler.captureSession) } }
关键说明
videoGravity设置:*.resizeAspectFill*:画面填充整个View,保持比例但会裁剪超出部分,适合全屏无黑边场景*.resizeAspect*:保持画面比例,View剩余区域留黑边,适合完整显示画面的场景
- 视频方向适配:通过监听界面方向,同步更新预览层的
videoOrientation,确保画面旋转后显示正常 - 会话预设:根据实际需求选择合适的分辨率,高分辨率会带来更高的性能消耗
内容的提问来源于stack exchange,提问作者NumberOne
相关产品推荐
相关产品推荐

