Rotation Only in One Viewcontroller

Rotation only in one ViewController

This is for Swift 4 and Swift 5. You can use the follow code in your AppDelegate.swift :

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
guard let rootViewController = self.topViewControllerWithRootViewController(rootViewController: window?.rootViewController),
(rootViewController.responds(to: Selector(("canRotate")))) else {
// Only allow portrait (standard behaviour)
return .portrait;
}
// Unlock landscape view orientations for this view controller
return .allButUpsideDown;
}

private func topViewControllerWithRootViewController(rootViewController: UIViewController!) -> UIViewController? {
guard rootViewController != nil else { return nil }

guard !(rootViewController.isKind(of: (UITabBarController).self)) else{
return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UITabBarController).selectedViewController)
}
guard !(rootViewController.isKind(of:(UINavigationController).self)) else{
return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UINavigationController).visibleViewController)
}
guard !(rootViewController.presentedViewController != nil) else {
return topViewControllerWithRootViewController(rootViewController: rootViewController.presentedViewController)
}
return rootViewController
}

You can then make a custom UIViewController rotate by overriding shouldAutorotate

iPhone - allow landscape orientation on just one viewcontroller

You can't support the landscape orientation only for one of the viewcontrollers if you use shouldAutorotateToInterfaceOrientation method of UIViewController.

You have only two choice whether all viewcontrollers support the landscape or no viewcontrollers support it.

If you want to support the landscape only for one, You need to detect device rotation and manually rotate views in the viewcontroller.

You can detect the device rotation by using Notification.

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(didRotate:)
name:UIDeviceOrientationDidChangeNotification
object:nil];

Then, you can rotate your views when you detect the device rotation.

- (void)didRotate:(NSNotification *)notification {
UIDeviceOrientation orientation = [[notification object] orientation];

if (orientation == UIDeviceOrientationLandscapeLeft) {
[xxxView setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
} else if (orientation == UIDeviceOrientationLandscapeRight) {
[xxxView setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
} else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
[xxxView setTransform:CGAffineTransformMakeRotation(M_PI)];
} else if (orientation == UIDeviceOrientationPortrait) {
[xxxView setTransform:CGAffineTransformMakeRotation(0.0)];
}
}

How to lock orientation just for one view controller?

This code should work:

    override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}

override func shouldAutorotate() -> Bool{
return false
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return UIInterfaceOrientation.Portrait
}

If it is now working for you, then I suppose your controller is in some another controller(UINavigationController, UITabBarController, UISplitViewController). In this case you need to use this code in that parent controller.

If your navigation controller contain more than one view controller, and you need to disable orientation only for some of them, then you need to inherit UINavigationController class and write there something like:

class NavigationController: UINavigationController {

var shouldRotate: Bool = true

override func supportedInterfaceOrientations() -> Int {
return shouldRotate ? Int(UIInterfaceOrientationMask.Portrait.rawValue) : Int(UIInterfaceOrientationMask.All.rawValue)
}

override func shouldAutorotate() -> Bool{
return shouldRotate
}
}

Then in controller that you need to disable orientation you can disable it for your navigation controller:

class ViewController: UIViewController {

var lastControllerRotationStatus: Bool?

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)

if let navigationController = self.navigationController as? NavigationController {
lastControllerRotationStatus = navigationController.shouldRotate
navigationController.shouldRotate = false
}
}

override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)

if let navigationController = self.navigationController as? NavigationController {
navigationController.shouldRotate = lastControllerRotationStatus ?? true
}
}
}

But remember, that you need to restore old rotation status after your controller will be pushed out navigation controller. In this example I'm saving rotation status before changing it, and restoring it after controller disappeared. Also you can use some other approach. For example you can overload UINavigationController method popViewController, and there set shouldRotate to false.

The same approach with variable setting from controller you can use for controlling rotation from AppDelegate method application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow) -> Int

Then you do not need to inherit from navigation controller.

Your AppDelegate class code will look like:

class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

var shouldRotate = true
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {

return shouldRotate ? Int(UIInterfaceOrientationMask.All.rawValue) : Int(UIInterfaceOrientationMask.Portrait.rawValue)

}

}

And your controller code will look like:

class ViewController: UIViewController {

var lastControllerRotationStatus: Bool?

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)

if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
lastControllerRotationStatus = appDelegate.shouldRotate
appDelegate.shouldRotate = false
}
}

override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)

if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
appDelegate.shouldRotate = lastControllerRotationStatus ?? true
}
}
}

Force landscape mode in one ViewController using Swift

It may be useful for others, I found a way to force the view to launch in landscape mode:

Put this in the viewDidLoad():

let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")

and,

override var shouldAutorotate: Bool {
return true
}

Only ONE VIEW landscape mode

I am gonna suppose you are targeting iOS 7 here (using XCode 5.1, I think I am right).

First, you have to understand that in order to open even just one view out of over 40 in landscape, your app should allow both landscape and portrait interface orientations.
It is the case by default, but you can check it in your target's settings, General tab, Deployment Info section (see screenshot below).

enter image description here

Then, because you allowed both landscape and portrait for the entire app, you will have to tell every portrait-only UIViewController that it should not autorotate, adding this method's implementation:

- (BOOL)shouldAutorotate {
return NO;
}

Finally, for your specific landscape-only controller, and because you said you are presenting it modally, you can just implement these methods:

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeLeft; // or Right of course
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}

Hope this will help,

How to rotate to landscape only one view controller

In your AppDelegate.swift :

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if let navigationController = self.window?.rootViewController as? UINavigationController {
if navigationController.visibleViewController is YourViewController {
return UIInterfaceOrientationMask.all
} else {
return UIInterfaceOrientationMask.portrait
}
}
return UIInterfaceOrientationMask.portrait
}


Related Topics



Leave a reply



Submit