如何使 AVFoundation 预览视图占据 SwiftUI 中的所有屏幕,而不考虑安全区域?

Posted

技术标签:

【中文标题】如何使 AVFoundation 预览视图占据 SwiftUI 中的所有屏幕,而不考虑安全区域?【英文标题】:How to make the AVFoundation Preview View to occupy all screen in SwiftUI, disregarding the safe area? 【发布时间】:2021-01-19 15:45:10 【问题描述】:

我正在使用this code

import SwiftUI
import UIKit
import AVFoundation

class PreviewView: UIView 
    private var captureSession: AVCaptureSession?

    init() 
        super.init(frame: .zero)

        var allowedAccess = false
        let blocker = DispatchGroup()
        blocker.enter()
        AVCaptureDevice.requestAccess(for: .video)  flag in
            allowedAccess = flag
            blocker.leave()
        
        blocker.wait()

        if !allowedAccess 
            print("!!! NO ACCESS TO CAMERA")
            return
        

        // setup session
        let session = AVCaptureSession()
        session.beginConfiguration()

        let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera,
            for: .video, position: .unspecified) //alternate AVCaptureDevice.default(for: .video)
        guard videoDevice != nil, let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice!), session.canAddInput(videoDeviceInput) else 
            print("!!! NO CAMERA DETECTED")
            return
        
        session.addInput(videoDeviceInput)
        session.commitConfiguration()
        self.captureSession = session
    

    override class var layerClass: AnyClass 
        AVCaptureVideoPreviewLayer.self
    

    required init?(coder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

    var videoPreviewLayer: AVCaptureVideoPreviewLayer 
        return layer as! AVCaptureVideoPreviewLayer
    

    override func didMoveToSuperview() 
        super.didMoveToSuperview()

        if nil != self.superview 
            self.videoPreviewLayer.session = self.captureSession
            self.videoPreviewLayer.videoGravity = .resizeAspect
            self.captureSession?.startRunning()
         else 
            self.captureSession?.stopRunning()
        
    


struct PreviewHolder: UIViewRepresentable 
    func makeUIView(context: UIViewRepresentableContext<PreviewHolder>) -> PreviewView 
        PreviewView()
    

    func updateUIView(_ uiView: PreviewView, context: UIViewRepresentableContext<PreviewHolder>) 
    

    typealias UIViewType = PreviewView


struct DemoVideoStreaming: View 
    var body: some View 
        VStack 
            PreviewHolder()
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
    

在 SwiftUI 上实现 AVFoundation 摄像头。

这很好用,但我希望预览视图填满所有 iPhone 屏幕区域,而不考虑安全区域。

我对 SwiftUI 很陌生。

我已经尝试过所有常规嫌疑人,例如在DemoVideoStreaming 的主体上使用.edgesIgnoringSafeArea(.all)

有什么想法吗?

【问题讨论】:

将视频重力设置为:.resizeAspectFill 【参考方案1】:

将视频重力改为.resizeAspectFill

self.videoPreviewLayer.videoGravity = .resizeAspectFill

【讨论】:

另一个question of mine如果你想试试你的知识......?

以上是关于如何使 AVFoundation 预览视图占据 SwiftUI 中的所有屏幕,而不考虑安全区域?的主要内容,如果未能解决你的问题,请参考以下文章

AVFoundation 图像方向在预览中偏离了 90 度,但在相机胶卷中很好

如何使控件占据堆栈内的实际大小

如何设置约束,以使视图的宽度至少等于某个宽度时为0

使用 AV Foundation 时正确裁剪捕获的图像

AVFoundation PhotoApp - 在图像保存在库中之前无法使闪存正常工作

AVFoundation - 如何在捕获图像之前将 Flash 设置为自动/关闭