I'm writing an iOS application with some fixed (portrait) views and some orientation dependent views (portrait, lanscape left and landscape right).
The views are contained in a Custom Navigation Controller based on the following code:
class CustomNavigationViewController: UINavigationController {
override func supportedInterfaceOrientations() -> Int {
return self.topViewController.supportedInterfaceOrientations()
}
override func shouldAutorotate() -> Bool {
return self.topViewController.shouldAutorotate()
}
}
I'm implementing supportedInterfaceOrientations()
and shouldAutorotate()
inside nav child controllers.
Here is a Test Controller
class TestViewController: UIViewController {
var shouldRotate: Bool = false
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.shouldRotate = true
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
convenience init(rotation shouldRotate: Bool) {
self.init(nibName: "TestViewController", bundle: nil)
self.shouldRotate = shouldRotate
}
override func supportedInterfaceOrientations() -> Int {
if shouldRotate == false {
return UIInterfaceOrientation.Portrait.rawValue
} else {
return super.supportedInterfaceOrientations()
}
}
override func shouldAutorotate() -> Bool {
return shouldRotate
}
override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
println("from: \(fromInterfaceOrientation.rawValue)")
}
@IBAction func buttonTapped(sender: AnyObject) {
let newvc = TestViewController(rotation: true)
self.navigationController?.pushViewController(newvc, animated: true)
}
}
The first controller is instantiated inside the AppDelegate
with rotation: false
. The other controllers are created with rotation: true
and pushed after tapping the button.
Here is a screenshot of the view:
If I change orientation on the controllers after the first one (the rotable ones) I get the following result:
The controller xib uses autolayout and if I rotate the device before tapping the button it works as expected with the view filling the whole screen.
Also, if I tap the back button while the phone is in landscape the first view is locked in this state:
I'm deploying the app to iOS 8.
How can I make the first view portrait only and the other views correctly layed out after a rotation?
It's probably doesn't matter since it's only printing out a debug message, but don't forget that didRotateFromInterfaceOrientation(_:)
was depreciated in iOS 8 with viewWillTransitionToSize(_:withTransitionCoordinator:)
taking it's place for responsibilities of a change in view size (which includes rotation).
I think you're on the right track, but instead of overriding both shouldAutorotate()
and supportedInterfaceOrientations()
only override supportedInterfaceOrientations()
.
I just did a quick POC to see if it would work. I'm not setting a flag when creating the view controller (and using Swift 2) but you get the idea:
class RotatingViewController: UIViewController {
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.All
}
}
class FixedViewController: UIViewController {
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
}
class NavigationController: UINavigationController {
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return self.topViewController?.supportedInterfaceOrientations() ?? UIInterfaceOrientationMask.All
}
}
I think what's happening in your demo is that when you're transitioning to a view controller that is fixed, you're asking it to go into a portrait orientation (which it is) but then not allowing the screen to rotate back to portrait mode.
So.. just try deleting your 'shouldAutorotate()' in your CustomNavigationViewController
and see if that works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With