19

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()
1110
  • 7,829
  • 55
  • 176
  • 334
  • Did it work for you? – Erik Apr 16 '15 at 16:46
  • No. When I move code to viewdidlayoutsubviews it doesn't work at all. On the view I have uiview and tableciew bellow it. And it seams that autolayout somehow increase uiview height and that is why Camera is not same size like uiview. I don't know how to handle it. – 1110 Apr 16 '15 at 17:19
  • Please provide me with more code to help diagnose this. – Erik Apr 16 '15 at 21:48
  • did you try CGRectMake(0, 0, ParentView.width,ParentView.hight); ? to set frame of cameraView. – Ajay Gabani Apr 20 '15 at 12:01
  • @1110 I'm having the same problem now, how do you solved it? thanks! – kaseOga Oct 13 '15 at 15:51

5 Answers5

18

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()
Erik
  • 1,246
  • 13
  • 31
0

To set priviewLayer constraints as like below code so it will occupied whole screen.

Leading Space = 0 from mainView
Top Space = 0 from mainView
Bottom Space = 0 from mainView 
Trailing Space = 0 from mainView

Hope this help you.

Jatin Patel - JP
  • 3,725
  • 2
  • 21
  • 43
0

This worked for me in Swift 4.2

Just set your AVCaptureVideoPreviewLayer's instance frame to Parent view's frame like below in viewDidLayoutSubviews() function :

override func viewDidLayoutSubviews(){
        super.viewDidLayoutSubviews()
        avCaptureVideoPreviewLayerInstance.frame = self.parentView.bounds
    }
Prashant Gaikwad
  • 3,493
  • 1
  • 24
  • 26
-1

If you want your layer to fill the UIView properly, you might as well define constraints for it :

self.camView.layer.addSublayer(previewLayer)
self.camView.layer.layoutManager = CAConstraintLayoutManager.layoutManager();
self.camView.layer.addConstraint(CAConstraint.constraintWithAttribute(CAConstraintAttribute.MinX, relativeTo: self.camView.layer, attribute: CAConstraintAttribute.MinX, scale: 1, offset: 0));
self.camView.layer.addConstraint(CAConstraint.constraintWithAttribute(CAConstraintAttribute.MaxX, relativeTo: self.camView.layer, attribute: CAConstraintAttribute.MaxX, scale: 1, offset: 0));
self.camView.layer.addConstraint(CAConstraint.constraintWithAttribute(CAConstraintAttribute.Width, relativeTo: self.camView.layer, attribute: CAConstraintAttribute.Width, scale: 1, offset: 0));
self.camView.layer.addConstraint(CAConstraint.constraintWithAttribute(CAConstraintAttribute.Height, relativeTo: self.camView.layer, attribute: CAConstraintAttribute.Height, scale: 1, offset: 0));
session.startRunning()
Dalzhim
  • 1,970
  • 1
  • 17
  • 34
-2

If you are using autolayout then just do:

  1. Set your camera view x=0 and with to screen size
  2. Apply leading and trailing constraint to superView

Hope this will help you.

Christian Garbin
  • 2,512
  • 1
  • 23
  • 31
bLacK hoLE
  • 781
  • 1
  • 7
  • 20