Change orientation programmatically with button - iOS
Asked Answered
M

3

17

I have a view controller and I would like to have the following experience. Inside the view controller i got a button which force rotate the orientation to landscape right.

In Deployment Info - Device Orientation i have enabled "Landscape Right" and "Portrait".

I want to mention that in my device i have enabled the "Portrait Orientation Lock" that's why i want a button to rotate the orientation programmatically with the following code.

let rotateButton: UIButton = {
    let btn = UIButton(type: .system)
    btn.setTitle("Rotate", for: .normal)
    btn.setTitleColor(.red, for: .normal)
    btn.addTarget(self, action: #selector(rotateTapped), for: .touchUpInside)
    return btn
}()

@objc func rotateTapped() {
    let value = UIInterfaceOrientation.landscapeRight.rawValue
    UIDevice.current.setValue(value, forKey: "orientation")
}

So the code above works properly and the screen is rotating. Although i want when the user rotates back to Portrait, the screen to rotate to portrait again without any button pressed. When the "Portrait Orientation Locked" is on, the screen is not rotating back to portrait.

I've tried the following codes with no luck.

1)

    NotificationCenter.default.addObserver(self, selector: #selector(rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)


@objc func rotated() {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape") //when the user taps the button this is being printed.
    } else {
        print("Portrait") //when the user rotates back to portrait this is NOT being printed.
    }
}

and 2)

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.current.orientation == .landscapeRight {
        let value = UIInterfaceOrientation.portrait.rawValue
        UIDevice.current.setValue(value, forKey: "orientation")
    }
}

Any idea of what can it be to change back to portrait when user rotates the phone again?

Milzie answered 17/5, 2018 at 8:35 Comment(0)
C
23

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

The above code has already been tested by me and it is working fine. In case the above code is not worked for you, Then execute it after some delay using performSelector.

Update 09 Feb 2023(iOS 16)

class OrientationManager {
    static var landscapeSupported: Bool = false
}

AppDelegate.swift

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
  if OrientationManager.landscapeSupported {
      return .landscape
   }
   return .portrait    
}

When you want to change the orientation on button click

@IBAction func btnChangeClick(){
        DispatchQueue.main.async {
            OrientationManager.landscapeSupported = !OrientationManager.landscapeSupported
            let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
            windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: OrientationManager.landscapeSupported ? .landscape : .portrait))
            self.setNeedsUpdateOfSupportedInterfaceOrientations()
        }
    }
Cestoid answered 17/5, 2018 at 8:47 Comment(5)
the code above as i understand is when user presses a button (or w/e) and want to rotate the screen programmatically to landscape. right?Milzie
what about iOS 13?Absolution
I do not check above code with iOS 13. If you found any concern then let me knowCestoid
@HiteshSurani - Any idea on implementing this on SwiftUI ?Hysterectomy
Sorry Buds, I never tried with the SwiftUI.Cestoid
E
3
var currentOrientation: UIInterfaceOrientation = UIApplication.shared.statusBarOrientation
var value = .landscapeRight
UIDevice.current.setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()
Emmenagogue answered 17/5, 2018 at 11:8 Comment(1)
Please improve your answer by explaining what that code is about. Thank you.Simeon
U
0
 @property (nonatomic) UIDeviceOrientation m_CurrentOrientation ;

/* You need to declare these code in your ViewDidload or ViewWillAppear */

- (void)viewDidLoad

   {

   [super viewDidLoad];

   [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

   [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object: nil];
}

/* Now Our Device will give a notification whenever we change the orientation of our device,So you can control your code or program using the current orientation */

- (void)deviceOrientationDidChange:(NSNotification *)notification

 {

 //Obtaining the current device orientation

 /* Where self.m_CurrentOrientation is member variable in my class of type UIDeviceOrientation */

 self.m_CurrentOrientation = [[UIDevice currentDevice] orientation];

    // Do your Code using the current Orienation 

 }
Unwonted answered 13/6, 2023 at 15:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.