My app build with ECSlidingViewController 2.0 as the sliding menu. I would like to disable the rotate for only one UIViewController . all my UIViewController start with UINavigationController.
I have make a SubClass of UINavigationController to implement the methods and assign the subclass to all UINavigationController in the sotryboard. but it does not work. it seems the code not triggered.
Inside MyNavigationController.m :
#import "MyNavigationController.h"
#import "ContactUsViewController.h"
#interface MyNavigationController ()
#end
#implementation MyNavigationController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (BOOL)shouldAutorotate {
NSLog(self.topViewController.description);
if ([self.topViewController isMemberOfClass:[ContactUsViewController class]]){
return NO;
}else{
return YES;
}
}
#end
ContactUsViewController is the UIViewController i don't want to rotate.
5 steps (I am running with Storyboard and IOS 7)
Subclass the ECSlidingViewController. (eg. MyECSlidingViewController)
Create your own shouldAutorotate and supportedInterfaceOrientations in the MyECSlidingViewController.
SubClass the UINavigationController and assign to all your existing UINavigationController. (eg. MyNavigationController)
Create your own shouldAutorotate and supportedInterfaceOrientations in the MyNavigationController.
in the UIViewController you want to set to Portrait only.
MyECSlidingViewController.m
-(BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
MyNavigationController.m
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
YourViewController.m
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
Hope it helps !
Related
I want to lock single viewcontroller in iPhone and iPad.
This below code is working perfectly in iPhone 4,5,6 iPad, iPad 2 ,iPad retina.
But not working in iPad pro.
#implementation UINavigationController (Orientation)
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
-(BOOL)shouldAutorotate
{
return YES;
}
#end
This above code is written in my view controller which view controller i do not want to rotate.
Write this below code in view controller, which view controller u want to lock in portrait mode
#implementation UINavigationController (Orientation)
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
-(BOOL)shouldAutorotate
{
return YES;
}
#end
#pragma mark Orientation
-(BOOL)shouldAutorotate
{
[super shouldAutorotate];
return NO;
}
-(NSUInteger) supportedInterfaceOrientations {
[super supportedInterfaceOrientations];
// Return a bitmask of supported orientations. If you need more,
// use bitwise or (see the commented return).
return UIInterfaceOrientationMaskPortrait;
// return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
- (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation {
[super preferredInterfaceOrientationForPresentation];
// Return the orientation you'd prefer - this is what it launches to. The
// user can still rotate. You don't have to implement this method, in which
// case it launches in the current orientation
return UIInterfaceOrientationPortrait;
}
And now do this below changes in your plist file
Write this in your view controller which you don't want to rotate
This will prevent any rotation.
The view controller class you don't want to rotate should have this.
- (BOOL)shouldAutorotate
{
return NO;
}
The containing navigation controller class should have this.
- (BOOL)shouldAutorotate
{
return [self.topViewController shouldAutoRotate];
}
This will only rotate to portrait
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
i just create a new single view application,and write three funcs in ViewController.m file.
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscape;
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
First Question
I expect the Simulator rotate my view,but the view orientation is Portrait. And I find the third func not called in ViewController. why?
Second Question
I read some blogs , they said if shouldAutorotate return NO, the func supportedInterfaceOrientations will not called,but in my test, this func called several times,why?
You have to use a UINavigationController subclass (not sure your using navigation in your project...) and implement those methods in the subclass. Do not forget to set your subclass as view-controller navigation controller
Example for navigation controller subclass:
// add this in your CustomNavigationController.h file
#import <UIKit/UIKit.h>
#interface CustomNavigationController : UINavigationController <UINavigationControllerDelegate>
#end
// add this in your : CustomNavigationController.m file
#import "CustomNavigationController.h"
#interface CustomNavigationController ()
#end
#implementation CustomNavigationController
- (BOOL)shouldAutorotate {
return [self.visibleViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations {
return [self.visibleViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [self.visibleViewController preferredInterfaceOrientationForPresentation];
}
#end
I have an iOS app with 2 view controllers namely - FirstViewController and SecondViewController. My window's rootViewController is UINavigationController.
FirstViewController is supposed to work ONLY in portrait mode and SecondViewController ONLY in Landscape mode.
Searching all over Stackoverflow I found out that for iOS6 and above I have to create a category over UINavigationController and override -supportedInterfaceOrientations
THE PROBLEM
Starting from FirstViewController. Now my phone being in Portrait mode, I push SecondViewController, the view loads in portrait mode. Once I rotate my phone to be in landscape the view will rotate to landscape ( and from this point onwards will not return to portrait at all ).
When I pop back FirstViewController will be in Portrait again ( no matter what the orientation of the phone ).
I want that SecondViewController shouldn't be displayed in Portrait mode at all. I've racked my brains all day...cannot find a solution.
APPDELEGATE
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
ViewController *vc = [[ViewController alloc] init];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:vc];
[self.navigationController setNavigationBarHidden:YES];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
FirstViewController
- (IBAction)btnClicked:(id)sender
{
SecondViewController *vc = [[SecondViewController alloc] init];
[self.navigationController pushViewController:vc animated:NO];
}
#pragma mark - Rotation handlers
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
SecondViewController
- (IBAction)btnClicked:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - Rotation handlers
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
}
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeRight;
}
UINavigation Category
#implementation UINavigationController (Rotation)
-(BOOL)shouldAutorotate
{
//return [self.topViewController shouldAutorotate];
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
#end
Well, it's a bit late but here is what I figured.
While there are many solutions available for the case when FirstVC is Portrait and Second can be Portrait and Landscape, I couldn't find any good solution to this problem (First Portrait ONLY and Second Landscape ONLY). Here is what I did:
Embed both view controllers in their own Navigation Controllers. Create two new classes, say FirstNavController and SecondNavController subclassing UINavigationController. Use these as your navigation controllers. (If you are using StoryBoards, select the Navigation Controller, go to Identity Inspector and change 'Class' field).
Now, in FirstNavController, add:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
And in SecondNavController:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
You will have to present the SecondNavController modally.
Nothing needs to be done in your View Controllers. Make sure you add all required orientations in your application settings.
The only drawback of this method is that both views are not in the same navigation stack, as second was presented modally, so you won't see a back button. But you can add a cancel/dismiss button yourself and call dismissViewControllerAnimated in SecondVC.
in my previous app i have done it
first you need to enable Portrait , Landscape left , Landscape right Orientation to project
Now
set below code to your FirstViewController
-(void) viewWillAppear:(BOOL)animated{
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
}
- (BOOL)shouldAutorotate
{
return NO;
}
set below code to your secondViewController
#define degreesToRadian(x) (M_PI * (x) / 180.0)
#implementation UINavigationController (Rotation_IOS6)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
#end
#interface secondViewController ()
#end
#implementation secondViewController
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
#end
My requirement is this my 1st viewcontroller open in Portrait mode only.and when user goes to 2nd viewcontroller i want that controller in Landscape mode how may i do this
i tried this code
1st ViewController.m
- (BOOL)shouldAutorotate
{
returnc YES;
}
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface
{
return (interface==UIInterfaceOrientationMaskPortrait);
}
Code for 2nd ViewController.m
- (BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
//return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
this will not working fine for me.
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
}
UPDATED:
You can do this by creating category of UINaviagationController
code for .h file is
#interface UINavigationController (autorotation)
-(BOOL)shouldAutorotate;
-(NSUInteger)supportedInterfaceOrientations;
and code for .m file is
#implementation UINavigationController (autorotation)
-(BOOL)shouldAutorotate
{
UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation;
[self.topViewController shouldAutorotate];
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
#end
paste following code in viewcontroller .m file of second view controller (under #implementation section)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
Now select the second view controller in storyboard (Selection indicated by blue border around view controller), go to the attribute inspector (right side 'shield' like image) change the orientation to landscape.. That's it.. .Tell me if it doesn't work for u. ..:)
I am solving my problem using Category....
Add new files and select Category and make subclass UINavigationController class.
here is the code for category for .h
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#interface UINavigationController (orientation)
#end
code for .m file
#import "UINavigationController+orientation.h"
#implementation UINavigationController (orientation)
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
AppDelegate * delegate=(AppDelegate *)[[UIApplication sharedApplication]delegate];
if (delegate.islandscape)
{
// for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
return UIInterfaceOrientationMaskLandscape;
}
return UIInterfaceOrientationMaskPortrait;
}
#end
isLandscape is declared in App delegate to check weather First view controller or secondView Controller isLandscape is Bool.
Now FirstViewController.m file i want that in Portarit mode so used this code
- (IBAction)PlayClicked:(id)sender
{
AppDelegate * delegate=(AppDelegate *)[[UIApplication sharedApplication]delegate];
self.navigationController.navigationBarHidden=YES;
delegate.islandscape=YES;
ViewController * v=[[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
[self presentViewController:v animated:NO completion:nil];
//[self dismissViewControllerAnimated:YES completion:nil];
[self.navigationController pushViewController:v animated:YES];
}
- (NSInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
and SecondViewController i want that in Landscape mode used this one.
delegate.islandscape=NO; // called transfer to Category
- (NSInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
I have a scenario in which I have a UITabbarController with 5 tabs. Each tab contains a UINavigationController.
Now in one of the UINavigationController rootViewController, when I select an option, another viewcontroller is pushed. Now I want the another view controller to be Landscape only.
Following is the code of my UITabBarController n UINavigationController category for Orientation
#implementation UITabBarController (rotation)
-(BOOL)shouldAutorotate
{
if ([self.selectedViewController respondsToSelector:#selector(shouldAutorotate)]) {
return [self.selectedViewController shouldAutorotate];
}
else {
return YES;
}
}
- (NSUInteger)supportedInterfaceOrientations
{
if ([self.selectedViewController respondsToSelector:#selector(supportedInterfaceOrientations)]) {
return [self.selectedViewController supportedInterfaceOrientations];
}
else if(DEVICE_IS_IPAD)
return UIInterfaceOrientationMaskAll;
else
return UIInterfaceOrientationMaskPortrait;
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
if ([self.selectedViewController respondsToSelector:#selector(supportedInterfaceOrientations)]) {
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
return 0;
}
#end
#implementation UINavigationController (AutoRotationForwarding)
-(BOOL)shouldAutorotate
{
if ([self.topViewController respondsToSelector:#selector(shouldAutorotate)]) {
return [self.topViewController shouldAutorotate];
}
else {
return YES;
}
}
-(NSUInteger) supportedInterfaceOrientations {
if([self.topViewController respondsToSelector:#selector(supportedInterfaceOrientations)])
{
return [self.topViewController supportedInterfaceOrientations];
}
return UIInterfaceOrientationMaskPortrait;
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
if ([self.topViewController respondsToSelector:#selector(supportedInterfaceOrientations)]) {
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
return UIInterfaceOrientationPortrait | UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight | UIInterfaceOrientationPortraitUpsideDown;
}
#end
and the code for the ViewController which I want to be Landscape only is :
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
if(DEVICE_IS_IPAD)
return UIInterfaceOrientationMaskLandscape;
else
return UIInterfaceOrientationMaskPortrait;
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
The Main issue is preferredInterfaceOrientationForPresentation is not at all called for UITabbarController or UINavigationBarController or even the view controller which I want to show.
Could you please let me know what am I doing wrong?
Thanks.
May be you forgot to addsupportedInterfaceOrientationsForWindow to your AppDelegate?
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskAll;
}
Beware of nil. I was following a similar approach of subclassing UINavigationController to relay the rotation messages to the topViewController. It worked great except the time the application launched. When you launch the application there is no topViewController (yet) but the OS needs to determine the supported orientation NOW AND for the the top-most viewController (the UINavigationController). If you fail to to provide an answer at the right time the UINavigationController will appear in the wrong orientation.
Note: PreferredInterfaceOrientationForPresentation is not called for UINavigationController
If your are using a UINavigationController as the root window
controller, it will be its shouldAutorotate &
supportedInterfaceOrientations which would be called.
iOS6: supportedInterfaceOrientations not working (is invoked but the interface still rotates)