【问题标题】:Preview layer not being constrained to UIView预览层不受 UIView 限制
【发布时间】:2020-02-05 20:38:25
【问题描述】:

我下面的 Swift 代码试图将 previewLayer 限制在名为 camera view 的 UIView 的边界内。然而,这并没有发生。 previewLayer 比约束 cameraView UIView 大得多。 cameraView 通过情节提要约束进行约束。我只希望这 2 个对象的位置和大小相同。

           import AVFoundation;import UIKit
    class ViewController: UIViewController, AVCaptureFileOutputRecordingDelegate {
    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {

    }


    var captureSession = AVCaptureSession()
    var sessionOutput = AVCaptureStillImageOutput()
    var movieOutput = AVCaptureMovieFileOutput()
    var previewLayer = AVCaptureVideoPreviewLayer()

    @IBOutlet var cameraView: UIView!



    override func viewWillAppear(_ animated: Bool) {


        let devices = AVCaptureDevice.devices(for: AVMediaType.video)
        for device in devices {
            if device.position == AVCaptureDevice.Position.front{


                do{

                    let input = try AVCaptureDeviceInput(device: device )

                    if captureSession.canAddInput(input){

                        captureSession.addInput(input)
                        sessionOutput.outputSettings = [AVVideoCodecKey : AVVideoCodecType.jpeg]

                        if captureSession.canAddOutput(sessionOutput){

                            captureSession.addOutput(sessionOutput)




                        }

                        captureSession.addOutput(movieOutput)

                        captureSession.startRunning()

                        _ = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
                        let documentURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
                        let fileURL = documentURL.appendingPathComponent("tempImage.jpg")
                        try? FileManager.default.removeItem(at: fileURL)
                        movieOutput.startRecording(to: fileURL, recordingDelegate: self)


                        let deadlineTime = DispatchTime.now() + .seconds(1)
                        DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
                            print("test")
                            self.movieOutput.stopRecording()
                        }



                    }

                }
                catch{

                    print("Error")
                }

            }
            viewDidAppear(animated )
        }

        func viewdidappeare(_ animated: Bool) {
            previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
            self.previewLayer.frame = self.cameraView.bounds
            previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
            previewLayer.connection!.videoOrientation = AVCaptureVideoOrientation.portrait
            self.cameraView.layer.insertSublayer(self.previewLayer, at: 0)





        }






    func captureOutput(captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAtURL outputFileURL: NSURL!, fromConnections connections: [AnyObject]!, error: NSError!) {
        print("FINISHED \(error)")
        // save video to camera roll
        if error == nil {
            UISaveVideoAtPathToSavedPhotosAlbum(outputFileURL.path!, nil, nil, nil)
        }
    }

    }
    }

【问题讨论】:

    标签: swift uiview constraints avfoundation avcapture


    【解决方案1】:

    你可以尝试如下:

    override func viewDidAppear(_ animated: Bool) { 
           super.viewDidAppear(animated)
           self.previewLayer.frame = self.cameraView.bounds
     }
    

    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
    previewLayer.connection!.videoOrientation = AVCaptureVideoOrientation.portrait
    self.cameraView.layer.insertSublayer(self.previewLayer, at: 0)
    

    所以您的完整更新代码:

    import AVFoundation
    import UIKit
    
    class ViewController: UIViewController, AVCaptureFileOutputRecordingDelegate {
    
        func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
    
        }
    
    
        var captureSession = AVCaptureSession()
        var sessionOutput = AVCaptureStillImageOutput()
        var movieOutput = AVCaptureMovieFileOutput()
        var previewLayer = AVCaptureVideoPreviewLayer()
    
        @IBOutlet var cameraView: UIView!
    
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            self.previewLayer.frame = self.cameraView.bounds
    
        }
    
        override func viewWillAppear(_ animated: Bool) {
    
    
            let devices = AVCaptureDevice.devices(for: AVMediaType.video)
            for device in devices {
                if device.position == AVCaptureDevice.Position.front{
    
    
                    do{
    
                        let input = try AVCaptureDeviceInput(device: device )
    
                        if captureSession.canAddInput(input){
    
                            captureSession.addInput(input)
                            sessionOutput.outputSettings = [AVVideoCodecKey : AVVideoCodecType.jpeg]
    
                            if captureSession.canAddOutput(sessionOutput){
    
                                captureSession.addOutput(sessionOutput)
    
                                previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    
                                previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
                                previewLayer.connection!.videoOrientation = AVCaptureVideoOrientation.portrait
                                self.cameraView.layer.insertSublayer(self.previewLayer, at: 0)
    
    
                            }
    
                            captureSession.addOutput(movieOutput)
    
                            captureSession.startRunning()
    
                            _ = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
                            let documentURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
                            let fileURL = documentURL.appendingPathComponent("tempImage.jpg")
                            try? FileManager.default.removeItem(at: fileURL)
                            movieOutput.startRecording(to: fileURL, recordingDelegate: self)
    
    
                            let deadlineTime = DispatchTime.now() + .seconds(1)
                            DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
                                print("test")
                                self.movieOutput.stopRecording()
                            }
    
    
    
                        }
    
                    }
                    catch{
    
                        print("Error")
                    }
    
                }
            }
        }
    
        func captureOutput(captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAtURL outputFileURL: NSURL!, fromConnections connections: [AnyObject]!, error: NSError!) {
            print("FINISHED \(error)")
            // save video to camera roll
            if error == nil {
                UISaveVideoAtPathToSavedPhotosAlbum(outputFileURL.path!, nil, nil, nil)
            }
        }
    }
    

    【讨论】:

    • 没有任何影响的预览层仍然是相同的大小。
    • 这段代码所做的是将uiview放在预览层上的约束位置。所以我可以看到uiview。但是预览层仍然占据了整个屏幕。
    • 从您的代码self.cameraView = self.view 中删除行并检查我的代码
    • 还把截图放在你的问题中你得到了什么?
    • 添加了屏幕截图并更新了上面的代码。在正确的轨道上,但预览层仅占视图的 1/4。
    【解决方案2】:

    问题在于,当父级更改其大小时,子图层不会自动调整大小。您需要手动执行此操作,例如在layoutSublayers:

    override func layoutSublayers(of layer: CALayer) {
        previewLayer.bounds = cameraView.frame
    }
    

    【讨论】:

    • 我将代码放入作用域,但出现此错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-26
    • 2021-06-29
    • 1970-01-01
    • 2018-03-15
    相关资源
    最近更新 更多