添加 AVCaptureVideoPreviewLayer 子视图时 UIView 忽略大小限制

Posted

技术标签:

【中文标题】添加 AVCaptureVideoPreviewLayer 子视图时 UIView 忽略大小限制【英文标题】:UIView ignoring size constraints when AVCaptureVideoPreviewLayer subview added 【发布时间】:2015-05-18 19:15:16 【问题描述】:

你好,周一快乐!

我正在尝试构建一个与 Instagram 外观相似的自定义相机。

首先,我使用 Storyboard 添加一个 UIView,将 UIView 垂直和水平居中,并通过 storyboard 将宽度和高度设置为 200。

然后,在我的代码中,我将 AVCaptureVideoPreviewLayer 添加到我的 UIView,我称之为 cameraView,然后将 AVCaptureVideoPreviewLayer 的框架设置为我的 UIView 框架。

问题: UIView 的宽度和高度约束似乎被忽略了。相机预览应该在视图的中心,但它不是。我在这里做错了什么?我想它与预览层有关。或者也许我需要使用 UIImageView 而不是 UIView?

任何意见将不胜感激!谢谢!

这是一个截图,它看起来像... 注意:突出显示图像以查看截图边缘的位置,对此感到抱歉。

我的代码:

extension String 
func stripCharactersInSet(chars: [Character]) -> String 
    return String(filter(self) find(chars, $0) == nil)



class MyCameraViewController: UIViewController 

let session = AVCaptureSession()
var captureDevice: AVCaptureDevice?
var previewLayer: AVCaptureVideoPreviewLayer?
var stillImageOutput = AVCaptureStillImageOutput()
var imageData: NSData!

@IBOutlet weak var capturePhotoButton: UIButton!
@IBOutlet weak var flashButton: UIButton!
@IBOutlet weak var cameraView: UIView!

override func prefersStatusBarHidden() -> Bool 
    return true


override func viewDidLoad() 
    super.viewDidLoad()
    //flashButton.hidden = true

    if(session.canSetSessionPreset(AVCaptureSessionPresetHigh)) 
        session.sessionPreset = AVCaptureSessionPresetHigh
     else 
        println("Cannot Set session Preset to AVCaptureSessionPresetPhoto")
    

    let devices = AVCaptureDevice.devices()
    for device in devices 
        if(device.hasMediaType(AVMediaTypeVideo))
            if(device.position == AVCaptureDevicePosition.Front)
                captureDevice = device as? AVCaptureDevice
                if captureDevice != nil 
                    beginSession()

                
            
        
    


func setCaptureDevice() 
    let devices = AVCaptureDevice.devices()
    for device in devices 
        if(device.hasMediaType(AVMediaTypeVideo))
            if(device.position == AVCaptureDevicePosition.Back)
                captureDevice = device as? AVCaptureDevice

            
        
    



@IBAction func flashButtonPressed(sender: UIButton) 
    if captureDevice!.hasFlash 
        if captureDevice!.isFlashModeSupported(AVCaptureFlashMode.On) 
            if (captureDevice!.lockForConfiguration(nil)) 
                if (captureDevice!.flashActive) 
                    captureDevice!.flashMode = AVCaptureFlashMode.Off
                    flashButton.setTitle("Flash Off", forState: UIControlState.Normal)
                 else 
                    captureDevice!.flashMode = AVCaptureFlashMode.On
                    flashButton.setTitle("Flash On", forState: UIControlState.Normal)
                
            
            captureDevice!.unlockForConfiguration()
        
    


@IBAction func switchCamera(sender: UIButton) 
    let currentCameraInput: AVCaptureInput = session.inputs[0] as! AVCaptureInput
    session.removeInput(currentCameraInput)

    let newCamera: AVCaptureDevice?
    if(captureDevice!.position == AVCaptureDevicePosition.Back)
        println("Setting new camera with Front")
        flashButton.hidden = true
        newCamera = self.cameraWithPosition(AVCaptureDevicePosition.Front)
     else 
        println("Setting new camera with Back")
        flashButton.hidden = false
        newCamera = self.cameraWithPosition(AVCaptureDevicePosition.Back)
    

    let newVideoInput = AVCaptureDeviceInput(device: newCamera!, error: nil)
    if(newVideoInput != nil) 
        session.addInput(newVideoInput)
     else 
        println("Error creating capture device input")
    
    captureDevice! = newCamera!
    session.commitConfiguration()



func cameraWithPosition(position: AVCaptureDevicePosition) -> AVCaptureDevice 
    let devices = AVCaptureDevice.devices()
    for device in devices 
            if(device.position == position)
                return device as! AVCaptureDevice
            
    
    return AVCaptureDevice()


func beginSession() 
    if(captureDevice!.isFocusModeSupported(AVCaptureFocusMode.ContinuousAutoFocus)) 
            captureDevice?.focusMode = AVCaptureFocusMode.ContinuousAutoFocus
        

    var err : NSError? = nil
    //Add Input, which is my captureDevice
    session.addInput(AVCaptureDeviceInput(device: captureDevice, error: &err))
    if err != nil 
        println("error: \(err?.localizedDescription)")
    
    previewLayer = AVCaptureVideoPreviewLayer(session: session)



    //self.view.layer.addSublayer(previewLayer)
    cameraView.layer.addSublayer(previewLayer)

    //previewLayer?.frame = self.view.layer.frame
    previewLayer?.frame = cameraView.layer.frame

    session.startRunning()


struct imageViewStruct 
    static var image: UIImage?


@IBAction func shotPress(sender: UIButton) 
    stillImageOutput.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
    if session.canAddOutput(stillImageOutput) 
        session.addOutput(stillImageOutput)
    
    var videoConnection = stillImageOutput.connectionWithMediaType(AVMediaTypeVideo)

    if videoConnection != nil 
        stillImageOutput.captureStillImageAsynchronouslyFromConnection(stillImageOutput.connectionWithMediaType(AVMediaTypeVideo))
             (imageDataSampleBuffer, error) -> Void in
                self.imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
                var dataProvider = CGDataProviderCreateWithCFData(self.imageData)
                var cgImageRef = CGImageCreateWithJPEGDataProvider(dataProvider, nil, true, kCGRenderingIntentDefault)
                var image = UIImage(CGImage: cgImageRef, scale: 1.0, orientation: UIImageOrientation.Up)

                imageViewStruct.image = image

                //self.uploadPhoto(image!)

                self.presentPhotoEditViewController(image!)                    
        



func setupPhotoEditor() 
    //Remove existing camera stuff
    previewLayer?.removeFromSuperlayer()


func presentPhotoEditViewController(imageToSend: UIImage) 
    let vc = self.storyboard?.instantiateViewControllerWithIdentifier("photoEditor") as! PhotoEditViewController
    self.presentViewController(vc, animated: true, completion: nil)


func uploadPhoto(image: UIImage) 
    let imageData = UIImagePNGRepresentation(image)
    let imageFile = PFFile(name:"image.png", data:imageData)

    var userPhoto = PFObject(className:getStringForVenue())
    userPhoto["imageFile"] = imageFile
    userPhoto.saveInBackground()


func getStringForVenue() -> String 

    let initialVenueString = LocViewController.variables.selectedVenue
    let chars: [Character] = ["'",",",":"," "]

    println(initialVenueString.stripCharactersInSet(chars))

    return initialVenueString.stripCharactersInSet(chars)


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.



【问题讨论】:

【参考方案1】:

您的方法 bigSession() 应该对 AVCaptureVideoPreviewLayer 进行一些设置:setVideoGravity 和 setFrame。

OBJ-C

[previewLayer setVideoGravity: AVLayerVideoGravityResizeAspectFill];
[previewLayer setFrame:self.cameraView.layer.bounds];

这将设置您的视频纵横比视图以适合您为其分配的视图层的框架。

【讨论】:

以上是关于添加 AVCaptureVideoPreviewLayer 子视图时 UIView 忽略大小限制的主要内容,如果未能解决你的问题,请参考以下文章

ASP在线添加字段

arcgis中如何添加图像数据?

C# 动态添加类动态添加类型代码添加类型

Eclipse IDE - 添加 jar?添加外部罐子?添加图书馆?

《VUE》怎么添加文字?添加文字操作流程

苹果cms10如何添加直播?