Swift UIInterfaceOrientation for Multiple views - ios

I have a navigation controller with multiple views. Most of the views are in portrait, and thus i lock it into portrait view by placing the following code in the Navigation View Controller
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> Int {
return UIInterfaceOrientation.Portrait.toRaw()
}
This works just fine, and locks all my views in portrait orientation. However, This is 1 view that needs to only be in Landscape. If I use the code above, it locks my Landscape View, into portrait mode, and thus cutting off most of the view.
Can anybody help me out with what to use in the Landscape view controller to lock this particular View in landscape only.
I was using this, but it doesn't work.
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Landscape.toRaw())
}
override func shouldAutorotate() -> Bool{
// This method is the same for all the three custom ViewController
return true
}

For a small app, the solution I generally use is to have the navigation controller ask the view itself for it's rotation preference:
override func supportedInterfaceOrientations() -> Int {
return visibleViewController.supportedInterfaceOrientations()
}
override func shouldAutorotate() -> Bool {
return visibleViewController.shouldAutorotate()
}
Then, in each of your view controllers, you can override shouldAutorotate and and supportedInterfaceOrientations to give each controller the behavior you want.
One additional trick, to ensure that your view can rotate back to it's desired rotation, you can use this to to conditionally allow rotation back to portrait:
override func shouldAutorotate() -> Bool {
return !UIInterfaceOrientationIsPortrait(self.interfaceOrientation)
}

Related

Force one viewcontroller to be only landscape

In my swift project i have all my viewcontroller to only portrait and i want only 1 view controller to be only landscape
My settings here
To do this , you have to set the Settings for both portrait and landscape and all the following code in each view controller except in which you want a landscape view
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
For further help check here

Lock one view orientation in iOS

I'm trying to lock one view of my app in portrait mode. I have a top navigation controller view and multiple nested scenes.
I found many answers to lock orientation question and tried the code below, but it works only partially. Let the scenes A and B, where A has a segue to B, and B is locked in portrait orientation. If I go to the B scene, turn the device to the landscape position and back to A, the orientation is inherited from previous B (portrait).
How can I make the A scene recognize the actual device orientation?
Navigation controller
internal override func shouldAutorotate() -> Bool {
return visibleViewController!.shouldAutorotate()
}
"B" View controller
override func shouldAutorotate() -> Bool {
if UIDevice.currentDevice().orientation == .Portrait {
return true
}
return false
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
override func viewDidLoad() {
super.viewDidLoad()
let orientation = UIInterfaceOrientation.Portrait.rawValue
UIDevice.currentDevice().setValue(orientation, forKey: "orientation")
}
As I understand your question you want to know how to get the current device orientation.
Try this...
var orientation = UIDevice.currentDevice().orientation

iOS How to replicate Youtube App player rotation?

Any idea about how the feature I show in this video is done?
It looks like the touch on the "expand" button force an orientation change for the device (infact when I swipe I'm pulling the control centre out).
Anyway only the video player seems to rotate. the scrollview underneath keeps its portrait orientation.
Looks like they're presenting the player controller with a custom segue animation, while having the player controller supporting only landscape.
Try presenting a view controller that has these implemented, like so:
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}
override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return UIInterfaceOrientation.LandscapeLeft
}
override func shouldAutorotate() -> Bool {
return false
}
Then the device should be in landscape. All you have left is to do the custom transition animation between the two and you're done.
From the docs:
preferredInterfaceOrientationForPresentation
If your view controller implements this method, your view controller’s
view is shown in the preferred orientation

UIViewController changes orientation while told not to do so

I have a UIViewController where I override those 2 methods:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
override func shouldAutorotate() -> Bool {
return false
}
My device orientation is ticked for Portrait, Landscape Left & Right.
I cleaned the build folder.
My problem: when I go to landscape, the app changes the orientation.
Any idea what's wrong. I thought overriding those two methods should be enough but it seems not.
Since your view controller is embedded in a UINavigationController and overridding shouldAutorotate() in the respective view controller alone wont work since it checks the shouldAutoRotate() of the UINavigationController/UITabBarController and therefore you will have to create a extension of UINavigationController
extension UINavigationController {
public override func shouldAutorotate() -> Bool {
return visibleViewController.shouldAutorotate()
}
}
And within the respective view controller wherever you want to lock the orientation as per your requirement override shouldAutoRotate()
override func shouldAutorotate() -> Bool {
return false
}

iOS ViewController doesn't layout properly after orientation change

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.
Problem is because shouldAutorotate return false.
Your FixedViewController should return shouldAutorotate value true, but supportedInterfaceOrientations should be for example only portrait.
Why do you need it?
When you come back (by using popViewController or dismissViewController) to your FixedViewController (which supports only portrait mode) from another RotateViewController in landscape mode, it should autorotate, to come back to portrait mode

Resources