Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set camera view to fill it's parent view

I don't know if this problem is something about auto layout or I am doing something wrong.
I have a UIViewController and one UIView inside of it.
And I am using AVCaptureSession to put camera view inside of it.
Problem is that when I camera view loads inside of view it doesn't fill that view so I have gaps on the left and right side.
What I am trying to do is to fill whole UIView with camera.
This is my code:

...
@IBOutlet weak var camView: UIView!
var previewLayer    : AVCaptureVideoPreviewLayer!

override func viewDidLoad() {
...
previewLayer = AVCaptureVideoPreviewLayer.layerWithSession(session) as! AVCaptureVideoPreviewLayer
        previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
previewLayer.frame = self.camView.layer.bounds
self.camView.layer.addSublayer(previewLayer)
session.startRunning()
like image 983
1110 Avatar asked Apr 09 '15 09:04

1110


Video Answer


1 Answers

You need to conduct the setup after your subviews are layed out. In viewDidLayoutSubviews

Add view

Add outlet

Add Constraints

-(void)viewDidLayoutSubviews
{
    [self setupAVCapture];
}


- (void)setupAVCapture {
    NSError *error = nil;

    AVCaptureSession *session = [AVCaptureSession new];
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
        [session setSessionPreset:AVCaptureSessionPreset640x480];
    else
        [session setSessionPreset:AVCaptureSessionPresetPhoto];

    // Select a video device, make an input
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];

    if ([session canAddInput:deviceInput])
        [session addInput:deviceInput];

    AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];
        [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];

    previewLayer.frame = self.camView.bounds;
    [self.camView.layer addSublayer:previewLayer];
    [session startRunning];
}

What was likely happening to you is that the bounds were not accurately set yet in your viewDidLoad as the subviews have yet to be laid out according to their constraints. When you instead setup the frame for the previewLayer in viewDidLayoutSubviews it will adopt the correct orientation. Be careful though, you will also need to adjust the preview on rotation and what not and modify the code I used. Sorry it isn't in swift, but that shouldn't matter. Just move your instantiation and setup into viewDidLayoutSubviews

So for your code, you should do something like this:

override func viewDidLayoutSubviews() {
...
previewLayer = AVCaptureVideoPreviewLayer.layerWithSession(session) as! AVCaptureVideoPreviewLayer
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
previewLayer.frame = self.camView.layer.bounds
self.camView.layer.addSublayer(previewLayer)
session.startRunning()
like image 179
Erik Avatar answered Oct 13 '22 00:10

Erik