In my app, all view controllers are having Portrait orientation except one. So let's name it, "GameViewController". The GameViewController is sticked to Landscape orientation only.
This is how I'm showing it in landscape mode:
MyViewController.m:
It's always in Portrait orientation, and from where we'll be presenting GameViewController.
- (void) showGameView {
GameViewController *gameView = (GameViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"GameViewController"];
[self presentViewController:gameView animated:YES completion:nil];
}
AppDelegate.m
This is how we're maintaining Landscape orientation forGameViewController.
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if ([self.window.rootViewController.presentedViewController isKindOfClass: [GameViewController class]]) {
GameViewController *gameView = (GameViewController *) self.window.rootViewController.presentedViewController;
if (gameView.isPresented) {
return UIInterfaceOrientationMaskLandscape;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
else return UIInterfaceOrientationMaskPortrait;
}
We've requirement to dismiss GameViewController when app goes to background.
- (void)applicationDidEnterBackground:(UIApplication *)application {
if(self.window.rootViewController.presentedViewController) {
UIViewController *presentedVC = self.window.rootViewController.presentedViewController;
if([presentedVC isKindOfClass:[GameViewController class]]) {
GameViewController *gameView = (GameViewController *)self.window.rootViewController.presentedViewController;
gameView.isPresented = NO;
[gameView.presentingViewController dismissViewControllerAnimated:NO completion:nil];
}
}
}
GameViewController.m
We're setting these to make it available in AppDelegate.
- (void) awakeFromNib {
self.isPresented = YES;
}
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.isPresented = YES;
}
- (void) dismissView {
self.isPresented = NO;
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
Working as per expectation in following cases:
Open App
Open MyViewController
Call showGameView method
You will have a landscape orientation for GameViewController
Doesn't matters even if you would change phone to any orientation
Dismiss from GameViewController
Will come back to Portrait orientation for MyViewController
Everything looks good
Not working as per expectation in following cases:
Open App
Open MyViewController
Call showGameView method
Lock Phone
Change phone orientation to Landscape
Unlock phone, come back to the App
You will have a landscape orientation for MyViewController
Dismiss from GameViewController
Everything looks messed
This is app settings to handle different orientations:
Related
I have three view controller both are which are pushed on the navigation controller which I have subclassed in order to allow rotation in only Second View Controller, I do it like this,
- (BOOL)shouldAutorotate
{
if ([self.topViewController isKindOfClass:[SecondViewController class]])
return YES;
return NO;
}
I write this piece of code in my Custom Navigation Controller, The problem is that if I open my application in portrait mode and then change the orientation to landscape mode my View Controller does not rotate but even when my Second View Controller opens up it opens in portrait mode although I expect it to open in landscape mode as it supports rotation.
How can I achieve this?
You need to use attemptRotationToDeviceOrientation during navigation. You should override push/pop methods to call attemptRotationToDeviceOrientation with a small UI delay (dispatch_async)
#implementation CustomNavigationController
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[super pushViewController:viewController animated:animated];
[self updateOrientaion];
}
- (nullable UIViewController *)popViewControllerAnimated:(BOOL)animated
{
[self updateOrientaion];
return [super popViewControllerAnimated:animated];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
if ([self.topViewController isKindOfClass:[SecondViewController class]])
return UIInterfaceOrientationMaskAll;
return UIInterfaceOrientationMaskPortrait;
}
- (void)updateOrientaion
{
dispatch_async(dispatch_get_main_queue(), ^{
[UIViewController attemptRotationToDeviceOrientation];
});
}
#end
But when you pop to rootViewController of the UINavigationController supportedInterfaceOrientations is called for the rootViewController. So you also need to implement supportedInterfaceOrientations for the FirstViewController
#implementation FirstViewController
.......
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
#end
I am trying to programmatically create UI orientation (portrait and landscape) using Objective C for all devices. Here the problem is I have multiple view controllers. I want to use multiple orientation into particular view controller.
For Ex:
Splash screen (App delegate - Portrait)
Login screen (Portrait)
Home screen (Both)
If I controlled by below method into App delegate root class then I cant enable both orientation into home view controller. Its showing black screen.
- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskPortrait;
}
You can try by following implementation. What here doing is, we sends the interfaceorientation we need for the visible view controller from app delegate. For that fist finds the visible viewcontroler and gets its supported interface orientation, If supportedInterfaceOrientations method not implemented in the visible view controller, return default orientation.
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
UIViewController *topController = [self topmostViewController];
if ([topController respondsToSelector:#selector(supportedInterfaceOrientations)]) {
return [topController supportedInterfaceOrientations];
}
return UIInterfaceOrientationMaskAllButUpsideDown;
}
- (UIViewController *)topmostViewController {
UIViewController *topController = self.window.rootViewController;
return [self topViewControllerWithRootViewController:topController];
}
- (UIViewController *)topViewControllerWithRootViewController:(UIViewController *)rootViewController {
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.topViewController];// dont use visible view controller, since it will return the presented ViewController, it may be UIAlertController.
} else if (rootViewController.presentedViewController && ![rootViewController.presentedViewController isKindOfClass:[UIAlertController class]]) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}
And if you want to display any view controller with orientation other than UIInterfaceOrientationMaskAllButUpsideDown implement following method in your view controller
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return <whichever orientation you need>;
}
UPDATE:
Make sure that you selected only the orientations you needed for initial view controller in target settings.
Ref: Finding topmost view controller code from this answer with slight modification by addressing UIAlertcontroller presented case
I'm developing a new app in xcode and the app is in portrait view, but the video should be able to be in portrait and landscape view. I programmed this code but it doesn't work 100%
AppDelegate.h
#import <MediaPlayer/MediaPlayer.h>
#property (strong, nonatomic) MPMoviePlayerViewController *VideoPlayer;
AppDelegate.m
#synthesize VideoPlayer;
- (NSUInteger)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if ([[self.window.rootViewController presentedViewController]
isKindOfClass:[MPMoviePlayerViewController class]]) {
return UIInterfaceOrientationMaskAllButUpsideDown;
} else {
if ([[self.window.rootViewController presentedViewController]
isKindOfClass:[UINavigationController class]]) {
// look for it inside UINavigationController
UINavigationController *nc = (UINavigationController *)[self.window.rootViewController presentedViewController];
// is at the top?
if ([nc.topViewController isKindOfClass:[MPMoviePlayerViewController class]]) {
return UIInterfaceOrientationMaskAllButUpsideDown;
// or it's presented from the top?
} else if ([[nc.topViewController presentedViewController]
isKindOfClass:[MPMoviePlayerViewController class]]) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
}
return UIInterfaceOrientationMaskPortrait;
}
The problem with this code is if user closes video player while it was watching video in landscape mode the whole app turns to landscape view even though I disabled it in Xcode GUI, after closing video player(app is in landscape view) if user rotate device to portrait it switches to portrait view and after that it stays in portrait (regardless device rotation). How can I make that app switches to portrait view even if user closes video player while he/she was watching video in landscape mode?
Thanks!
After long researches, I finally figured out the solution.
1) Enable All orientations for your application.
2) Subclass your root Navigation controller, and implement this 2 methods
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
3) Subclass from MPMoviePlayerViewController
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
4) Now you should present subclassed MoviePlayerController, and all the stuff should work!
You almost got it right by adding the function in AppDelegate. The only problem is when user back from landscape video, the app become video. The solution is just here:
UIViewController *vc = [[self.window.rootViewController presentedViewController];
if ([vc isKindOfClass:[MPMoviePlayerViewController class]] &&
![vc isBeingDismissed]) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
The key here is to double check if the presented view controller is being dismiss (exiting).
I m developing iphone app. In that all viewconenter code heretroller support all orientation. But one of my navigationController stack content want to present one
viewcontroller in Landscape orientation only. I done this by creating one custon UINavigationController with rootviewcontroller as my modelviewcontroller ,it support only landscape mode and it works fine when the parentviewcontroller in portrait modd, but the parentviewcontroller in landscape it present modelview controller as landscape fine but after dismiss the modelViewcontroller the parentviewcontroller as portrait, but the self.view and subview are in landscape.
Please help me.. I put my code and screenshot as below..
.m file in custom navigationcontroller I done this..
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (BOOL) automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers {
return YES;
}
-(BOOL)shouldAutorotate
{
return YES;
}
.m file parentView
//This is my presentViewcintroller code
VideoPreviewViewController *videoPreviewVC = [[VideoPreviewViewController alloc]initWithNibName:#"VideoPreviewViewController" bundle:nil];
customNavigationController = [[CLNotRotatingNavController alloc]initWithRootViewController:videoPreviewVC];
[self.navigationController presentViewController:customNavigationController animated:YES completion:nil];
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
}
.m file in modelviewcontroller
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
My application is working fine for iOS5. But for iOS6 I am getting the following orientation problem.
I have a ViewController VC1. when you rotate (change the orientation to UIInterfaceOrientationLandscapeRight) I want to present another ViewController VC2 and when you rotate back I need to dismiss VC2 and the VC1 should be in Portrait mode.
I am using tabBar in my application and I want this feature only for the first tab.
In tabBar I have written
-(BOOL) shouldAutorotate
{
UINavigationController *nav = (UINavigationController *)self.selectedViewController;
if ([nav.topViewController isKindOfClass:[MainViewController class]])
{
return YES;
}
else
{
return NO;
}
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
//Here I am writing code for presenting view(using notifications)
// but When I rotate the device to landscape it's getting called but when I rotate back
//to portrait I not getting called.
}
Thank you.
Please try this with ios 6 :(Example)
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationPortrait | UIInterfaceOrientationLandscapeRight | UIInterfaceOrientationLandscapeLeft;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
}