8

I'm basically after the answer to this question AVCaptureVideoPreviewLayer orientation - need landscape except in Swift.

I'm targeting iOS 8 and AVCaptureVideoPreviewLayer doesn't seem to have a setVideoOrientation function.

How should I be detecting that the orientation has changed, and rotating AVCaptureVideoPreviewLayer appropriately?

Community
  • 1
  • 1
epalm
  • 4,283
  • 4
  • 43
  • 65

5 Answers5

24

Detect and apply it at viewWillLayoutSubviews or if you're using UIView subclass in layoutSubviews.

Here's how:

override func viewWillLayoutSubviews() {
                
    let orientation: UIDeviceOrientation = UIDevice.current.orientation

    previewLayer.connection?.videoOrientation = {
        switch (orientation) {
        case .portrait:
            return .portrait
        case .landscapeRight:
            return .landscapeLeft
        case .landscapeLeft:
            return .landscapeRight
        default:
            return .portrait
        }
    }()
}
mmackh
  • 3,550
  • 3
  • 35
  • 51
米米米
  • 970
  • 7
  • 9
  • thankyou sir... you saved my day... add this line before break will help previewLayer.frame = self.view.bounds – Arpan Sharma Jul 01 '16 at 11:12
  • 1
    This needs to be updated for the latest Swift. Take note that the videoOrientation is flipped from the device orientation for landscape modes. – Jeff Muir Sep 15 '17 at 05:35
1

update for Swift 3

  override func viewWillLayoutSubviews() {

    let orientation: UIDeviceOrientation = UIDevice.current.orientation
    print(orientation)

    switch (orientation) {
    case .portrait:
        videoPreviewLayer?.connection.videoOrientation = .portrait
    case .landscapeRight:
        videoPreviewLayer?.connection.videoOrientation = .landscapeLeft
    case .landscapeLeft:
        videoPreviewLayer?.connection.videoOrientation = .landscapeRight
    case .portraitUpsideDown:
            videoPreviewLayer?.connection.videoOrientation = .portraitUpsideDown
    default:
        videoPreviewLayer?.connection.videoOrientation = .portraitUpsideDown
    }
}
Erik Mueller
  • 330
  • 4
  • 10
0

For me I need it to change orientation when I rotate iPad left or right, the solution that helped me is:

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    let orientation = UIDevice.current.orientation

    switch (orientation) {
    case .portrait:
        videoPreviewLayer?.connection.videoOrientation = .portrait
    case .landscapeLeft:
        videoPreviewLayer?.connection.videoOrientation = .landscapeRight
    case .landscapeRight:
        videoPreviewLayer?.connection.videoOrientation = .landscapeLeft
    default:
        videoPreviewLayer?.connection.videoOrientation = .portrait
    }
}
clopex
  • 459
  • 6
  • 11
0

Xamarin Solution in ViewController;

public override void ViewWillLayoutSubviews()
    {
        base.ViewWillLayoutSubviews();

        var videoPreviewLayerConnection = PreviewView.VideoPreviewLayer.Connection;
        if (videoPreviewLayerConnection != null)
        {
            var deviceOrientation = UIDevice.CurrentDevice.Orientation;
            if (!deviceOrientation.IsPortrait() && !deviceOrientation.IsLandscape())
                return;

            var newVideoOrientation = VideoOrientationFor(deviceOrientation);
            var oldSize = View.Frame.Size;
            var oldVideoOrientation = videoPreviewLayerConnection.VideoOrientation;
            videoPreviewLayerConnection.VideoOrientation = newVideoOrientation;
        }
    }
vdidxho
  • 165
  • 1
  • 14
0

another solution in Swift 4 it would be using Notification.

        NotificationCenter.default.addObserver(self,
                                           selector: #selector(detected),
                                           name: 

UIDevice.orientationDidChangeNotification, object: nil)

and in selector function you can check the orientation:

let orientation: UIDeviceOrientation = UIDevice.current.orientation
switch orientation {
    case .portrait:
         stuff()
    case .landscapeLeft:
         stuffOther()
    case .landscapeRight
         stuffOther()
    default:
         stuffOther()
}

Remember to remove observer when is not necessary.

Very IMPORTANT: your physical iPhone must NOT have lock on rotation (I've lost 2 hour for this because in this case, the method are not intercepted :) ).

Alessio Campanelli
  • 970
  • 11
  • 19