Restrict orientation per view controller - ios

I want to say in each view controller which orientation he supports and restrict it to them. This is what I tried:
Use a custom navigation controller like in one of my old posts, but that doesn't seem to work anymore. The solution is similar to iOS 6 - (BOOL)shouldAutorotate not getting called for navigation controllers pushed viewControllers
I also tried Setting Orientation in Xamarin iOS, but the app crashes on the RootViewController. I get a NullReferenceException here.
Furthermore I tried IOS 8 : Restricting orientation on a View Controller from the deleted blog from Shri Chakraborty (shrixamarin). Here the app also crashes if I use application:supportedInterfaceOrientationsForWindow:, because the RootViewController is null. The solution seems to be similar to How do I restrict orientation per view controller in iOS7 in a navigation controller hierarchy
None of the solutions seems to work. Or do I miss something important? How can I restrict the orientation that view controller A is landscape only, view controller B is portrait only and view controller C can be shown in all available orientations?

Overriding GetSupportedInterfaceOrientations() in your view controller should solve the problem:
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations () {
return UIInterfaceOrientationMask.LandscapeRight;
}
The orientations you return here will be intersected with the app's allowed orientations (project properties) or with what you allow in your app delegate. So be sure to specify all orientations there or the maximum set of orientations you want to support.
See here for documentation.

Related

ViewController and SubView are not rotating correctly

I am working on a landscape view for a currently existing application. I believe I have autoRotate, supported interface, etc set up correctly, I am actually reusing code that works with a much simpler app. However when the simulator is rotated into landscape mode, the correct view loads, but the status bar and view stay with the short edge of the iPad. I've attached a screenshot and code. Is the problem with a view controller higher up in the chain, or the appdelegate? I've traced the called controllers in the debugger and it appears they are dismissed once this page is loaded. I am fairly new-ish to obj-c so it is possible this is something simple I am missing, but I have checked all attributes for the .xib file and everything looks copasetic.
Some of the code:
-(BOOL)shouldAutorotate
{
return NO;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;// | UIInterfaceOrientationMaskPortraitUpsideDown;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return NO;
}![enter image description here][2]
-(void)orientationChanged{
UIInterfaceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
if ((interfaceOrientation==UIInterfaceOrientationPortrait)||(interfaceOrientation ==UIInterfaceOrientationPortraitUpsideDown)){
self.view = self.portraitView;
} else {
self.view = self.landscapeView;
}
}
EDITS - This problem occurs on both iOS 7.1 and 6.1 and this is the first time any screen in the app supports a landscape view. To clarify the views, the portrait and landscape views are separate Views in single .xib file. The file owner class is set to the correct view controller class, and the parent view controller, a sales screen, should not rotate. It does not have a landscape view, but even with its autoRotate methods set to return YES the subview does not orient correctly.
Like 0x7ffffffff already said you need to allow rotation in your shouldAutorotate functions. Also you need to set up the supported rotation directions in your project setup.
First go to your project's settings:
Next you need to select all the orientations you want to support:
Another that is very important: ONLY the root View Controller will receive rotation events. If you nest a View Controller inside a View Controller then that nested Controller will not receive those events unless you wire them up manually from the parent. That's why I usually don't nest ViewControllers but use ad-hoc NSObjects or UIView implementations for nested views.
Last but not least: make sure your device is not rotation-locked: http://www.iphonefaq.org/archives/972915
The problem was occurring because a subclass of the customerView was not receiving the rotation notification. After tracking that class down it was a matter of setting up the NSNotificationCenter for orientation changes and then allowing autoRotation and supprotedInterfaceOrientations.

iOS Orientation Support both Landscape and Portrait on specific screen - NOT ALL Screens

Comrades,
I just would like to know, how to enable Landscape Orientation only on Specific screens? As of now, I selected Landscape Left and Right options in General Settings and enabled in Supported interface orientations (iPhone) in plist file for the device Orientation, but that impacts all the screens.
I have nearly 80 screens in my application, I need to support both Portrait and Landscape about 5 screens, rest of the screens should be shown only in Portrait mode.
Any help is greatly appreciated!
Thanks,
Ramesh
In General Settings (which just adjusts your plist), you need to select all possible supported orientations. Then, you need to limit them in your specific view controller. If you're using a NavBar or TabBar controller, you need add your limitation there.
From the UIViewController docs:
In iOS 6 and later, your app supports the interface orientations defined in your app’s Info.plist file. A view controller can override the supportedInterfaceOrientations method to limit the list of supported orientations. Typically, the system calls this method only on the root view controller of the window or a view controller presented to fill the entire screen; child view controllers use the portion of the window provided for them by their parent view controller and no longer participate directly in decisions about what rotations are supported. The intersection of the app’s orientation mask and the view controller’s orientation mask is used to determine which orientations a view controller can be rotated into.
To make this simpler, I created a category on UINavigationController that looks at the top-most view controller to determine it's rotation abilities. That way, in my specific view controllers that needed rotating, I could override those same methods and add landscape support.
#implementation UINavigationController (AutoRotation)
- (NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
- (BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
#end
Are your screens inside a UINavigationController? If so, I've noticed not all viewControllers can decide what orientations they support.

How to configure SWRevealViewController/PKRevealController/etc to handle orientation and presentation changes

I am using SWRevealViewController (https://github.com/John-Lluch/SWRevealViewController) to handle switching between two controllers, a "front" and a "rear".
The front controller is a UINavigationController and the rear controller is just a plain UIViewController that displays a list of menu items. The front UINavigationController pushes an instance of a view controller named FrontViewController. The rear UIViewController is an instance of RearViewController. The instance of SWRevealViewController is set as the root view controller once it is configured with the front and rear controllers, the delegate property of the reveal controller is set to the app delegate itself.
In both FrontViewController and RearViewController I am overriding shouldAutorotate and returning NO as well as overriding supportedInterfaceOrientations and returning UIInterfaceOrientationMaskPortrait.
However the app auto rotates and goes into Landscape while these two views are displaying when I rotate the device.
supportedInterfaceOrientations seems to only be invoked in FrontViewController but the value is not honored and the device rotates into landscape orientation.
I can't simply set the entire app to Portrait either because I have other detail views that I do want to support Landscape (movie player, etc).
How can I get SWRevealViewController working so I can restrict the app to Portrait in certain child views of the controller?
I have also noticed that the presentation changes are not being honored as well. In RearViewController I am overriding prefersStatusBarHidden to return YES but this method is never invoked. Similarly in FrontViewController I am overriding preferredStatusBarStyle to return UIStatusBarStyleLightContent but this method is never called either.
I have UIViewControllerBasedStatusBarAppearance set to YES in my plist.
UPDATE:
I have tried to use PKRevealController as suggested in the comments but the behavior is exactly the same. Supported orientations and status bar styles are completely ignore. supportedInterfaceOrientations on FrontViewController is the only override invoked but the return value of UIInterfaceOrientationMaskPortrait is not honored.
UPDATE 2:
I'm thinking that this is simply a limitation of these controls and they pretty much expect the support orientations to be the same throughout the application. I did however try MFSideMenu (https://github.com/mikefrederick/MFSideMenu) and it seems to handle supported orientations in different child views exactly as you would expect it to. I still don't have the status bar visibility and styles working, unfortunately.
To achieve this while not avoiding SWRevealViewController: Inside of it there is implemented method supportedInterfaceOrientations, which needs to be edited. I have done this:
- (NSUInteger)supportedInterfaceOrientations
{
UINavigationController* frontNavigationController = (UINavigationController*)self.frontViewController;
if ([frontNavigationController.visibleViewController isKindOfClass:[VCgallery class]]) {
return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationPortrait | UIInterfaceOrientationPortraitUpsideDown;
}
All my viewControllers are portrait only except those that are of class VCgallery, which can be both portrait and lanscape.
The solution ended up being to subclass PKRevealController and override supportedInterfaceOrientations, shouldAutorotate, preferredInterfaceOrientationForPresentation, prefersStatusBarHidden, and preferredStatusBarStyle.
While MFSideMenu did this for orientation it did not support status bar configurations. I also ran into a major bug with MFSideMenu that prevented me from using it in my project.
I made each method I override return a value from the appropriate controller depending on the circumstance. In the case orientation I return the value from self.frontViewController.topViewController (since I am using a UINavigation controller). Status bar style and visibility came from either self.frontViewController or self.leftViewController depending on the current state.
The same solution probably would have worked for SWRevealViewController as well but I preferred the API design of PKRevealController.
I figured subclassing would work from the beginning but I assumed that such a common scenario would be handled in the configuration of these controls.

iOS >> Device Orientation >> Screen is Not Supporting Upside Down

I have a screen that supports Device Orientation.
Everything is working fine except for the fact that when I rotate the device upside down (home button at top), the rotation doesn't work (it's stuck on the last landscape settings).
I know of several places needed be updated to support this:
In the VC itself, I added the methods:
In the Project Target, I updated as follow:
In the Storyboard VC Scene, I updated as follow:
What am I missing here?
You also have to allow rotating to all orientations in every parent view controller of the current main view controller. For example, if your view controller is in navigation controller, try subclassing it and override the same methods as in your example.
Edit: As #JordanC mentioned, since iOS 7 you can implement UINavigationControllerDelegate method to return custom supported orientations:
- (UIInterfaceOrientationMask)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController
As #eGanges mentioned the key point could be to subclass your UITabBarController (and override supportedInterfaceOrientations) if that is your initial view controller, in that case this is the only controller you should subclass (and of course you should add all the supported interface orientations to your app Info.plist file UISupportedInterfaceOrientations key)
Have you tested on real device?
anyway try this:
- (NSUInteger)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
}

After dismissModalViewController, view is in portrait mode

I have a detail view where i load a help view with a button. I am using [UIViewController presentModalViewController:animated:].
In help view I am dismissing the view with a button. I am using [UIViewController dismissModalViewControllerAnimated:].
The problem is, after dismissing the help view, the detail view is in portrait mode, regardless of which orientation the device is in.
In all the view controllers, I have implemented shouldAutoRotateToInterfaceOrientation: and returned YES.
I think there are two selective solution
1.Officially available in iOS 5.0 and later, you can implement
/* call this method when your return value from shouldAutorotateToInterfaceOrientation: changes
if the current interface orientation does not match the current device orientation, a rotation may occur provided all relevant view controllers now return YES from shouldAutorotateToInterfaceOrientation: */
+ (void)attemptRotationToDeviceOrientation
See also : http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIViewController_Class/Reference/Reference.html
2.Use the trick from Canopus's Answer. It's pretty fine with iOS 4.3 and earlier BUT It's not guarantee solution that owner answer has warned you.
Hope it helps you!

Resources