epalm
epalm

Reputation: 4433

How can I detect and apply landscape orientation to AVCaptureVideoPreviewLayer in Swift?

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?

Upvotes: 8

Views: 5942

Answers (5)

米米米
米米米

Reputation: 990

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
        }
    }()
}

Upvotes: 24

Alessio Campanelli
Alessio Campanelli

Reputation: 1030

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 :) ).

Upvotes: 0

vdidxho
vdidxho

Reputation: 355

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;
        }
    }

Upvotes: 0

clopex
clopex

Reputation: 459

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
    }
}

Upvotes: 0

Erik Mueller
Erik Mueller

Reputation: 350

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
    }
}

Upvotes: 1

Related Questions