自定义相机视图预览层加上大小的手机问题

Posted

技术标签:

【中文标题】自定义相机视图预览层加上大小的手机问题【英文标题】:Custom camera view preview layer Plus size phone issue 【发布时间】:2017-04-05 19:54:14 【问题描述】:

我在 UIViewController 中有一个自定义的相机视图,它不占用全屏。在它下面是一个集合视图,其中填充了带有“X”的图像的小缩略图,然后允许用户在将保留的图像上传到 Firebase 之前删除它们。

这一切在 iPhone 7 大小的屏幕上都很好用。但是在大码手机上,自定义摄像头视图的预览层并没有填满摄像头所在的整个 UIView。

override func viewWillAppear(_ animated: Bool) 
    super.viewWillAppear(animated)

    let deviceSession = AVCaptureDeviceDiscoverySession(deviceTypes:
        [.builtInDuoCamera, .builtInTelephotoCamera, .builtInWideAngleCamera], mediaType: AVMediaTypeVideo, position: .unspecified)

    for device in (deviceSession?.devices)! 
        if device.position == AVCaptureDevicePosition.back 
            do 
                let input = try AVCaptureDeviceInput(device: device)

                if captureSession.canAddInput(input) 
                    captureSession.addInput(input)

                    if captureSession.canAddOutput(sessionOutput) 
                        captureSession.addOutput(sessionOutput)

                        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
                        previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
                        previewLayer.connection.videoOrientation = .portrait

                        cameraView.layer.addSublayer(previewLayer)
                        cameraView.addSubview(takePhotoButton)

                        previewLayer.position = CGPoint(x: self.view.frame.width/2, y: self.cameraView.frame.height/2)
                        previewLayer.bounds = cameraView.frame

                        captureSession.startRunning()
                    
                
             catch let avError 
                print(avError)
            
        
    

在这里,我将预览层添加为 CameraView 的子层,它只是在界面构建器中添加的 UIView,具有约束以允许视图中的空间用于其下方的集合视图。

 previewLayer.position = CGPoint(x: self.cameraView.frame.width/2, y:   self.cameraView.frame.height/2)
 previewLayer.bounds = cameraView.frame

我不明白为什么作为子层添加的预览层在 Iphone7 和 Iphone 7 Plus 上的行为会有所不同? 特别是因为您可以在 Iphone 7 Plus 上看到,预览层周围的灰色表明 CameraView 被正确约束,为什么它的 frame.width 会有所不同。

似乎在 Plus 尺寸的手机上,预览层的大小与在普通尺寸的手机上保持相同,而 CameraView 本身正确地符合更大的手机屏幕。

这是界面构建器中的相关视图

这似乎是在大尺寸手机上发生的事情

【问题讨论】:

如果您尝试在控制器的viewDidLayoutSubviews() 方法中添加子视图而不是viewWillAppear() 怎么办?这听起来像是与自动布局相关的问题。 我会试试看,你是否建议将整个代码块移动到 viewDidLayoutSubviews()?不幸的是,我没有大号手机,所以需要等待试飞测试人员知道它是否有效。 我建议您将previewLayer.positionpreviewLayer.bounds 设置为viewDidLayoutSubviews()。您的问题很可能是在执行 viewWillAppear() 时,Autolayout 没有为实际设备大小重新计算 cameraView.frame,而是使用您在 Storyboard 中设置的大小。 viewDidLayoutSubviews() 方法仅用于此目的 - 使用为该特定设备重新计算的实际尺寸。 您可以尝试在 iPhone 7 Plus 模拟器中启动它,它应该显示占位符图片而不是捕获预览。 我发布了详细的答案。检查一下,让我知道它是否能解决您的问题。 【参考方案1】:

TL;DR:viewDidAppear() 方法中设置视图和图层的坐标和框架。


在执行viewWillAppear() 方法时,所有视图控制器的子视图都具有您在情节提要中设置的frame 值。您需要使用为实际设备大小重新计算的更新的cameraView.frame 值,正确设置您的previewLayer.positionpreviewLayer.boundsviewDidLayoutSubviews() 方法就是为了这个目的而存在的——在它执行的时候,所有视图的实际大小都会针对正在运行的特定设备应用程序重新计算。

viewDidLayoutSubviews() 可以被多次调用,这可能会导致创建视图/图层的多个实例。在视图控制器的生命周期中还有另一种方法,它只使用自动布局的子视图调用一次 - viewDidAppear()

所以你需要将你的previewLayer相关代码从viewWillAppear()移动到viewDidAppear()

【讨论】:

以上是关于自定义相机视图预览层加上大小的手机问题的主要内容,如果未能解决你的问题,请参考以下文章

相机预览层未显示

Android 自定义相机 Camera 预览变形拉伸问题

如何自定义相机视图并捕获叠加层中的部分?

android 相机 怎么改变相机预览界面大小

自定义相机预览图片

从 av 基础框架工作为 ios 开发自定义相机应用程序时,Camara 预览显示不正确?