How to force view controller orientation in iOS 8?

前端 未结 25 2086
太阳男子
太阳男子 2020-11-22 13:11

Before iOS 8, we used below code in conjunction with supportedInterfaceOrientations and shouldAutoRotate delegate methods to force app orie

相关标签:
25条回答
  • 2020-11-22 13:25

    This is what worked for me:

    https://developer.apple.com/library//ios/documentation/UIKit/Reference/UIViewController_Class/index.html#//apple_ref/occ/clm/UIViewController/attemptRotationToDeviceOrientation

    Call it in your viewDidAppear: method.

    - (void) viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
    
        [UIViewController attemptRotationToDeviceOrientation];
    }
    
    0 讨论(0)
  • 2020-11-22 13:25

    I have tried many solutions, but the one that worked for is the following:

    There is no need to edit the info.plist in ios 8 and 9.

    - (BOOL) shouldAutorotate {
        return NO;
    }   
    
    - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
        return (UIInterfaceOrientationPortrait | UIInterfaceOrientationPortraitUpsideDown);
    }
    

    Possible orientations from the Apple Documentation:

    UIInterfaceOrientationUnknown

    The orientation of the device cannot be determined.

    UIInterfaceOrientationPortrait

    The device is in portrait mode, with the device held upright and the home button on the bottom.

    UIInterfaceOrientationPortraitUpsideDown

    The device is in portrait mode but upside down, with the device held upright and the home button at the top.

    UIInterfaceOrientationLandscapeLeft

    The device is in landscape mode, with the device held upright and the home button on the left side.

    UIInterfaceOrientationLandscapeRight

    The device is in landscape mode, with the device held upright and the home button on the right side.

    0 讨论(0)
  • 2020-11-22 13:25

    I tried a few solutions in here and the important thing to understand is that it's the root view controller that will determine if it will rotate or not.

    I created the following objective-c project github.com/GabLeRoux/RotationLockInTabbedViewChild with a working example of a TabbedViewController where one child view is allowed rotating and the other child view is locked in portrait.

    It's not perfect but it works and the same idea should work for other kind of root views such as NavigationViewController. :)

    Child view locks parent orientation

    0 讨论(0)
  • 2020-11-22 13:28

    Orientation rotation is a little more complicated if you are inside a UINavigationController or UITabBarController. The problem is that if a view controller is embedded in one of these controllers the navigation or tab bar controller takes precedence and makes the decisions on autorotation and supported orientations.

    I use the following 2 extensions on UINavigationController and UITabBarController so that view controllers that are embedded in one of these controllers get to make the decisions.

    Give View Controllers the Power!

    Swift 2.3

    extension UINavigationController {
        public override func supportedInterfaceOrientations() -> Int {
            return visibleViewController.supportedInterfaceOrientations()
        }
        public override func shouldAutorotate() -> Bool {
            return visibleViewController.shouldAutorotate()
        }
    }
    
    extension UITabBarController {
        public override func supportedInterfaceOrientations() -> Int {
            if let selected = selectedViewController {
                return selected.supportedInterfaceOrientations()
            }
            return super.supportedInterfaceOrientations()
        }
        public override func shouldAutorotate() -> Bool {
            if let selected = selectedViewController {
                return selected.shouldAutorotate()
            }
            return super.shouldAutorotate()
        }
    }
    

    Swift 3

    extension UINavigationController {
        open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
            return visibleViewController?.supportedInterfaceOrientations ?? super.supportedInterfaceOrientations
        }
    
        open override var shouldAutorotate: Bool {
            return visibleViewController?.shouldAutorotate ?? super.shouldAutorotate
        }
    }
    
    extension UITabBarController {
        open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
            if let selected = selectedViewController {
                return selected.supportedInterfaceOrientations
            }
            return super.supportedInterfaceOrientations
        }
    
        open override var shouldAutorotate: Bool {
            if let selected = selectedViewController {
                return selected.shouldAutorotate
            }
            return super.shouldAutorotate
        }
    }
    

    Now you can override the supportedInterfaceOrientations method or you can override shouldAutoRotate in the view controller you want to lock down otherwise you can leave out the overrides in other view controllers that you want to inherit the default orientation behavior specified in your app's plist

    Disable Rotation

    class ViewController: UIViewController {
        override func shouldAutorotate() -> Bool {
            return false
        }
    }
    

    Lock to Specific Orientation

    class ViewController: UIViewController {
        override func supportedInterfaceOrientations() -> Int {
            return Int(UIInterfaceOrientationMask.Landscape.rawValue)
        }
    }
    

    In theory this should work for all complex view controller hierarchies, but I have noticed an issue with UITabBarController. For some reason it wants to use a default orientation value. See the following blog post if you are interested in learning about how to work around some of the issues:

    Lock Screen Rotation

    0 讨论(0)
  • 2020-11-22 13:28

    According to solution showed by @sid-sha you have to put everything in the viewDidAppear: method, otherwise you will not get the didRotateFromInterfaceOrientation: fired, so something like:

    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
        if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
            interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
            NSNumber *value = [NSNumber numberWithInt:interfaceOrientation];
            [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
        }
    }
    
    0 讨论(0)
  • 2020-11-22 13:30

    On Xcode 8 the methods are converted to properties, so the following works with Swift:

    override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.portrait
    }
    
    override public var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
        return UIInterfaceOrientation.portrait
    }
    
    override public var shouldAutorotate: Bool {
        return true
    }
    
    0 讨论(0)
提交回复
热议问题