How to Rotate Orientation Programmatically in Swift

How to change Device Orientation programmatically in Swift?

For each VC declare this variable w/ desired orientation. This is for portrait.

override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return .portrait }   

Then on appearance enforce the desired orientation.

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.setAnimationsEnabled(false)
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
UIView.setAnimationsEnabled(true)
}

Change orientation programmatically with button - iOS

I don't have a swift code. Below are the objective c code, It worked for me. You can convert it into swift as per your requirement.

Ojective C

UIInterfaceOrientation currentOrientation = [UIApplication sharedApplication].statusBarOrientation;
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];

Update

Swift 4.0

var value  = UIInterfaceOrientation.landscapeRight.rawValue
if UIApplication.shared.statusBarOrientation == .landscapeLeft || UIApplication.shared.statusBarOrientation == .landscapeRight{
value = UIInterfaceOrientation.portrait.rawValue
}

UIDevice.current.setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()

Above code already tested by me and it is working fine. Incase above code is not worked for you, Then execute it after some delay using performSelector.

iOS Swift 5 Change device orientation manually

One simple way to accomplish this is by setting your supported orientation on the AppDelegate (_:supportedInterfaceOrientationsFor:)

Create a local variable there

var orientation: UIInterfaceOrientationMask = .portrait

and then return that variable as supported orientation

    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return orientation
}

on the ViewController that you want to rotate with a touch of a button, you can change the supported orientation on the app delegate and than force the device orientation to change so that the view is rotated

    private func changeSupportedOrientation() {
let delegate = UIApplication.shared.delegate as! AppDelegate
switch delegate.orientation {
case .portrait:
delegate.orientation = .landscapeLeft
default:
delegate.orientation = .portrait
}
}

@IBAction func rotateButtonTapped(_ sender: UIButton) {
changeSupportedOrientation()
switch UIDevice.current.orientation {
case .landscapeLeft:
UIDevice.current.setValue(UIDeviceOrientation.portrait.rawValue, forKey: "orientation")
default:
UIDevice.current.setValue(UIDeviceOrientation.landscapeLeft.rawValue, forKey: "orientation")
}
}

this will force the orientation of the device to change and then rotate your view. If you tap on the button again the orientation will be back to .portrait

Please be careful of using this as you need to really consider your navigation stack to make sure that only the top of the navigation stack support rotation and can only be pop from the navigation stack after the orientation is set back to the original which is .portrait only.

How to change the device orientation programmatically and screen's rotation direction should be in clock wise direction

Each orientation in iOS has a raw value.

  1. portrait = 1
  2. portraitUpsideDown = 2
  3. landscapeLeft = 3
  4. landscapeRight = 4

You can change orientation based on these values.

Here is how I have done it in swift

  1. Rotate in clockwise direction:

    @IBAction func rotateClockwise(_ sender: Any) {


    let orientation = UIDevice.current.orientation
    print("Current state:",orientation.rawValue)
    var newOrientation: Int {
    switch orientation.rawValue {
    case 1:
    return 3
    case 2:
    return 4
    case 3:
    return 2
    case 4:
    return 1
    default:
    return 1
    }
    }


    UIDevice.current.setValue(newOrientation, forKey: "orientation")

    }

  2. Rotate in anti clockwise direction:

    @IBAction func rotateAntiClockwise(_ sender: Any) {

    let orientation = UIDevice.current.orientation
    print("Current state:",orientation.rawValue)
    var newOrientation: Int {
    switch orientation.rawValue {
    case 1:
    return 4
    case 2:
    return 3
    case 3:
    return 1
    case 4:
    return 2
    default:
    return 1
    }
    }


    UIDevice.current.setValue(newOrientation, forKey: "orientation")
    }

Note

Make sure to select all orientations in target - general

If that doesn't work add the following code to view controller class

override var supportedInterfaceOrientations: UIInterfaceOrientationMask { get { return .all } }

Programmatic constraints with screen rotation (swift)

It is important to remember that we should be working with size layouts, rather than portrait / landscape. With multitasking slide over / split views, it's not unusual to have your view have a different height:width ratio than the device itself.

There are various ways to handle this... here's one approach.

  • create an array of "wide layout" constraints
  • create an array of "narrow layout" constraints
  • create an array of "common" constraints - these apply whether in narrow or wide "orientation"
  • activate / deactivate the wide and narrow constraints, based on the size of the view

Try this example:

class ChildView1: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
backgroundColor = .blue
layer.cornerRadius = 16
}
}

class ChildView2: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
backgroundColor = .red
layer.cornerRadius = 16
}
}

class SampleViewController: UIViewController {

let cv1 = ChildView1()
let cv2 = ChildView2()

// array of constraints for "wide" layout
var wideConstraints: [NSLayoutConstraint] = []

// array of constraints for "narrow" layout
var narrowConstraints: [NSLayoutConstraint] = []

// just for clarity, array of constraints that apply for
// both wide and narrow layouts
var commonConstraints: [NSLayoutConstraint] = []

override func viewDidLoad() {
super.viewDidLoad()

cv1.translatesAutoresizingMaskIntoConstraints = false
cv2.translatesAutoresizingMaskIntoConstraints = false

view.addSubview(cv1)
view.addSubview(cv2)

let g = view.safeAreaLayoutGuide

commonConstraints = [
// cv1 will always be constrained top and leading
cv1.topAnchor.constraint(equalTo: g.topAnchor),
cv1.leadingAnchor.constraint(equalTo: g.leadingAnchor),

// cv2 will always be constrained trailing and bottom
cv2.trailingAnchor.constraint(equalTo: g.trailingAnchor),
cv2.bottomAnchor.constraint(equalTo: g.bottomAnchor),
]

// when narrow, cv1 on top of cv2
narrowConstraints = [
// constrain cv1 trailing
cv1.trailingAnchor.constraint(equalTo: g.trailingAnchor),
// constrain cv2 leading
cv2.leadingAnchor.constraint(equalTo: g.leadingAnchor),
// constrain cv2 top to cv1 bottom
cv2.topAnchor.constraint(equalTo: cv1.bottomAnchor),
// make them equal heights
cv2.heightAnchor.constraint(equalTo: cv1.heightAnchor),
]

// when wide, cv1 side-by-side cv2
wideConstraints = [
// constrain cv1 bottom
cv1.bottomAnchor.constraint(equalTo: g.bottomAnchor),
// constrain cv2 top
cv2.topAnchor.constraint(equalTo: g.topAnchor),
// constrain cv2 leading to cv1 trailing
cv2.leadingAnchor.constraint(equalTo: cv1.trailingAnchor),
// make them equal widths
cv2.widthAnchor.constraint(equalTo: cv1.widthAnchor),
]

// activate the commonConstraints
NSLayoutConstraint.activate(commonConstraints)

if view.frame.width > view.frame.height {
// wider than tall, so "landscape"
NSLayoutConstraint.activate(wideConstraints)
} else {
// taller than wide
NSLayoutConstraint.activate(narrowConstraints)
}
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { _ in
if size.width > size.height {
// we're transitioning to wider than tall
NSLayoutConstraint.deactivate(self.narrowConstraints)
NSLayoutConstraint.activate(self.wideConstraints)
} else {
// we're transitioning to taller than wide
NSLayoutConstraint.deactivate(self.wideConstraints)
NSLayoutConstraint.activate(self.narrowConstraints)
}
}, completion: {
_ in
// if you want to do somwthing after the transition
})

}

}

iPad orientation programmatically not working

When you set programmatically the orientation of the device. To perform the orientation animation the function

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask 

from AppDelegate is being called.

If you have set it there to return only UIInterfaceOrientationMask.portrait you will never see the transition.

Also I personally have these kind of problems and to solve this I had to programmaticaly force the phone to rotate to the current Orientation and then to rotate to the wanted orientation.

Example for phone to rotate landscapeLeft from portrait

func setOrientationToLandScapeOnly() {
appDelegate.shouldForceLandscapeOnly = true
appDelegate.shouldForcePortraitOnly = false
if UIDevice.current.userInterfaceIdiom == .phone {
switch UIApplication.shared.statusBarOrientation {
case .landscapeLeft, .landscapeRight:
return
default:
APIOrientationHandler.shared.setDeviceValueForOrientation(UIInterfaceOrientation.portrait.rawValue)
APIOrientationHandler.shared.setDeviceValueForOrientation(UIInterfaceOrientation.landscapeLeft.rawValue)
return
}
}
}

And inside AppDelegate.swift

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {

if shouldForcePortraitOnly {
return UIInterfaceOrientationMask.portrait
}

if shouldForceLandscapeOnly {
return UIInterfaceOrientationMask.landscape
}

if (UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad) {
return UIInterfaceOrientationMask.landscape
}

return UIInterfaceOrientationMask.portrait
}


Related Topics



Leave a reply



Submit