My app supports only Landscape. I've added an MPMoviePlayerController to the view of my view controller.
When I press full screen button, it works fine and it will rotate in Landscape only for iOS versions prior to iOS 5. However, in iOS 5.0+, it also supports portrait (only when I enter into full screen mode).
How can I prevent portrait support in iOS 5.0 and above?
Try subclassing MPMoviePlayerViewController and overriding the shouldAutorotatoToInterfaceOrientation method to only support landscape modes:
-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
if((toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight))
{
return true;
}
else
{
return false;
}
}
I resolved this problem thus: create custom navigation controller what support 2 orientation:
UIInterfaceOrientationLandscapeLeft && UIInterfaceOrientationLandscapeRight
More details:
1. Create custom navigation controller
CustomNavigationController.h file
#import <UIKit/UIKit.h>
#interface CustomNavigationController : UINavigationController
-(CustomNavigationController*)initWithRootViewController:(UIViewController *)rootViewController;
#end
CustomNavigationController.m file
#implementation IORNavigationController
-(CustomNavigationController*)initWithRootViewController:(UIViewController *)rootViewController
{
self = [super initWithRootViewController:rootViewController];
if (self)
{
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
2.In Appdelegate add self navigation controller
Appdelegate.h
#property (nonatomic, retain) CustomNavigationController* navigationController;
Appdelegate.m
self.navigationController = [[[CustomNavigationController alloc] initWithRootViewController:start] autorelease];
self.navigationController.view.autoresizesSubviews = YES;
window.rootViewController = self.navigationController;
[self.navigationController setNavigationBarHidden:YES];
And now you have app with two orientation and video in landscape orientation.
Related
I used this code to block the rotation before ios 7 (i was also using xibs, now storyboard)
- (BOOL)shouldAutorotate {
return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationPortrait;
}
now that i migrated to storyboard and ios7 it is not working, my view is still rotating.
UPDATE:
I solved this by adding this code to the delegate, now my previous code works like charm
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
if (self.fullScreenVideoIsPlaying) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else {
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
Atrik's code worked. Here is a more complete solution which allows locking and unlocking of portrait-mode-only even with the use of UINavigationController
appdelegate .h
#property (nonatomic) BOOL screenIsPortraitOnly;
appdelegate .m
#pragma mark - View Orientation
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
if (self.screenIsPortraitOnly) {
return UIInterfaceOrientationMaskPortrait;
}
else {
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
}
For all view controllers where I need Portrait Lock
If you haven't used a subclass which has the app delegate imported then don't forget to import the delegate. For most view controllers I use a subclass of UIViewController which at least does importation.
#import "AppDelegate.h"
I use this for all portrait locked viewcontrollers.
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:true];
[self portraitLock];
}
-(void) portraitLock {
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.screenIsPortraitOnly = true;
}
#pragma mark - interface posiiton
- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL) shouldAutorotate {
return NO;
}
ViewDidLoad runs before viewDidAppear so I run this in my subclass of UIViewController to unlock all screens. The viewWillAppear with the lock method is used only in the cotrollers which I need to lock the screen.
- (void)viewDidLoad
{
[super viewDidLoad];
[self portraitUnLock];
}
-(void) portraitUnLock {
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.screenIsPortraitOnly = false;
}
If you only want in landscape mode then you can do it with xcode project setting
go to Target > summary > support interface orientations
Or you can do a code
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
In XCode 5, which is required to be used for iOS7 development, you can go to your target and under Deployment Info uncheck everything except Portrait for device orientation.
If you don't want your app to rotate at all (no matter which view is active), you can click on your project in the Xcode sidebar, scroll down, and deselect Landscape Left and Landscape Right.
App Support: iOS6+
My app works in both portrait and landscape. But 1 controller should only works in a Portrait.
The problem is that when I am in landscape and push the view controller the new viewcontroller is in landscape as well until I rotate it to portrait. Then it's stuck in portrait as it should be.
Is it possible to always make it appear in portrait? Even if its parent is pushing it in landscape?
All the following code doesn't help
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
And this code works until and unless i am not pushing from landscape How to force a UIViewController to Portrait orientation in iOS 6
I solved this by adding following lines in ViewDidLoad
UIViewController *c = [[UIViewController alloc]init];
[self presentViewController:c animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];
First, you need to create a category:
UINavigationController+Rotation_IOS6.h
#import <UIKit/UIKit.h>
#interface UINavigationController (Rotation_IOS6)
#end
UINavigationController+Rotation_IOS6.m:
#import "UINavigationController+Rotation_IOS6.h"
#implementation UINavigationController (Rotation_IOS6)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
#end
Then, you implement these methods in your class that you want to be only landscape:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
In case you're using a UITabBarController, just replace the UINavigationController for UITabBarController.
This solution worked nice for me after a long search! I was in the same situation as you are now!
EDIT
So, I saw your sample. You need to make some changes.
1 - Create a new class for the UINavigationController category. Name the class UINavigationController+Rotation_IOS6 (.h and .m)
2 - You don't need to implement the method preferredInterfaceOrientationForPresentation. Your category should look like this:
#import "UINavigationController+Rotation_IOS6.h"
#implementation UINavigationController (Rotation_IOS6)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
#end
3 - In the class you want to rotate only in landscape, include this in the implementation, exactly like this:
// Rotation methods for iOS 6
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
4 - I would advice to also include the method for autorotation for iOS 5 inside the class you want in landscape:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight;
}
Please note that the answer below - do not work for iOS6 so I still need an answer!
My application is enabled only for Portrait mode.
However, if I embed a UIImagePickerController inside as a subview, and rotate the device, the top and bottom bar stays in the same location, however UIImagePickerController does rotate.
How can I prevent it from rotating?
This is the code:
[self.view.window addSubview:self.imagePickerController.view];
self.imagePickerController.showsCameraControls = NO;
self.imagePickerController.view.frame = CGRectMake(0, 90, 320, 320);
self.imagePickerController.allowsEditing = NO;
EDITED
I am using iOS6 where shouldAutorotate is not being calle
Add this UIImagePickerController category in your class,
#interface UIImagePickerController(Nonrotating)
- (BOOL)shouldAutorotate;
#end
#implementation UIImagePickerController(Nonrotating)
- (BOOL)shouldAutorotate {
return NO;
}
#end
include the following in your controller this will work, I'm just creating the category of UIImagePickerController
#interface UIImagePickerController (private)
- (BOOL)shouldAutorotate;
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;
- (NSUInteger)supportedInterfaceOrientations;
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
#end
#implementation UIImagePickerController (Private)
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate {
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
One possibility is to override the
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation;
method of UIImagePickerController. I'm not sure if this is the best possibility but it will work.
So if you only want your UIImagePickerController to be rotated to portrait use the following code
#interface PortraitUIImagePickerController : UIImagePickerController
#end
And the implementation should look like the following
#implementation PortraitUIImagePickerController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
}
#end
The category in the most voted answer works, but since it is discouraged to use categories, you can also make a subclass of UIImagePickerController and use that.
If you want to avoid rotating of the UIImagePickerController add the following class
UINonRotatableImagePickerController.h
#interface UINonRotatableImagePickerController : UIImagePickerController
#end
UINonRotatableImagePickerController.m
#implementation UINonRotatableImagePickerController
- (BOOL)shouldAutorotate
{
return NO;
}
#end
You have to change the UIImagePicker class in the storyboard to use UILandscapeImagePickerController, or if you allocate it in code, change
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
to
UIImagePickerController *picker = [[UINonRotatableImagePickerController alloc] init];
and include UINonRotatableImagePickerController.h in your code.
I'm having what seems to be a fairly common problem, but my searches and implementations of solutions have not worked out.
I've built a Cocos2d game that is intended to be landscape only, but needs to access Gamecenter. Gamecenter is working, with portrait mode enabled, but it's also allowing the game to flip to portrait mode too.
I've attempted the following fixes:
Game center login lock in landscape only in i OS 6
GameCenter authentication in landscape-only app throws UIApplicationInvalidInterfaceOrientation
Error in iOS 6 after adding GameCenter to a landscape-only cocos2d app
Cocos 2d 2.0 shouldAutorotate not working?
I believe the problem is that I've built the game using CCLayers instead of UIViewControllers
Example:
MenuLayer.h
#interface MenuLayer : CCLayer <GKAchievementViewControllerDelegate, GKLeaderboardViewControllerDelegate, UINavigationControllerDelegate>{
..my header info..
}
MenuLayer.m
...
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
-(BOOL)shouldAutorotate {
return [[UIDevice currentDevice] orientation] != UIInterfaceOrientationPortrait;
}
-(void)authenticateLocalPlayer
{
GKLocalPlayer * localPlayer= [GKLocalPlayer localPlayer];
if(localPlayer.authenticated == NO)
{
NSString *reqSysVer = #"6.0";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
{
[[GKLocalPlayer localPlayer] setAuthenticateHandler:(^(UIViewController* viewcontroller, NSError *error) {
if (viewcontroller != nil) {
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] presentModalViewController:viewcontroller animated:YES];
}else if ([GKLocalPlayer localPlayer].authenticated)
{
//do some stuff
}
})];
}
else
{
[localPlayer authenticateWithCompletionHandler:^(NSError *error){
if(localPlayer.isAuthenticated)
{
//Peform Additionl Tasks for the authenticated player.
}
}];
}
}
}
...
Since I've built the game using CCLayers instead of UIViewControllers, what alternatives do I have? Am I correct in assuming that CCLayers don't call use supportedInterfaceOrientations or shouldAutorotate?
Or am I supposed be changing this code somehow to fix the problem:
// Create a Navigation Controller with the Director
navController_ = [[UINavigationController alloc] initWithRootViewController:director_];
navController_.navigationBarHidden = YES;
This frustrated me for awhile too. After digging around for awhile on the 'Net I found a couple of sources and some worked with iOS 6, some with iOS5, but I had to make some modifications so that it worked the way I wanted on both iOS5 and iOS6. This is the code I am using, it works on my iPhone using 5.1 and 6. Note that the Game Center login still comes up in portrait orientation, there doesn't appear to be anything you can do about that. But the rest of the game will remain in landscape mode.
enable portrait mode as a supported orientation in your build settings (info.plist).
Create a new subclass of UINavigationController. Name this class whatever makes sense to you.
In your AppDelegate, include your new custom UINavigationController header file.
In your App Delegate, comment out the original call and instead call your custom class.
That should do the trick. Here is the code from my custom class:
#import <UIKit/UIKit.h>
#interface CustomNavigationViewController : UINavigationController
-(UIInterfaceOrientation) getCurrentOrientation;
#end
And the implementation file:
#import "CustomNavigationViewController.h"
#interface CustomNavigationViewController ()
#end
#implementation CustomNavigationViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// This is required to allow GameCenter to login in portrait mode, but only allow landscape mode for the rest of the game play/
// Arrrgg!
-(BOOL) shouldAutorotate {
return YES;
}
-(NSUInteger) supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
-(UIInterfaceOrientation) preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeRight; // or left if you prefer
}
-(NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
return UIInterfaceOrientationMaskLandscape;
else {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return [[UIDevice currentDevice] orientation] != UIInterfaceOrientationPortrait;
}
-(UIInterfaceOrientation) getCurrentOrientation {
return [[UIDevice currentDevice] orientation];
}
#end
Note that last method getCurrentOrientation isn't required I just put that in there in case I wanted to determine what the current orientation is.
The custom class is called in AppDelegate.m like this: (comment out the original code)
navController = [[CustomNavigationViewController alloc] initWithRootViewController:director];
window.rootViewController = navController;
navController.navigationBarHidden = YES;
[window makeKeyAndVisible];
Hope this helps.
I have QuickLook (QLPreviewController) almost working how I want it, but because of the images characteristics I don't want it to rotate into portrait orientation.I have it configured in the "shouldAutoRotateToInterfaceOrientation" method to only return yes for landscape rotations (see code below for details) but it is still rotating to portrait.
Note: The shouldAutoRotateToInterfaceOrientation is a direct copy that is used in all of my view controllers for this project and it is working in the other view controllers.
//
// documentViewer.m
//
#import "DocumentViewer.h"
#implementation DocumentViewer
#synthesize documents;
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
return YES;
else if (interfaceOrientation == UIInterfaceOrientationLandscapeRight)
return YES;
else
return NO;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
//-(void)viewWillAppear:(BOOL)animated {
//
// self.userInteractionEnabled = YES;
//}
//Nessary for Enabling User Interaction
- (BOOL)canBecomeFirstResponder {
return YES;
}
-(void) createList:(NSString *) document {
documents = [[NSArray arrayWithObjects:document, nil] retain];
}
-(NSInteger) numberOfPreviewItemsInPreviewController: (QLPreviewController *) controller {
return [documents count];
}
- (id <QLPreviewItem>) previewController: (QLPreviewController *) controller previewItemAtIndex: (NSInteger) index {
return [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[documents objectAtIndex:index] ofType:nil]];
}
#end
In AppDelegate.m replace
return UIInterfaceOrientationMaskAll;
with
return UIInterfaceOrientationMaskLandscape;
just like this:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskLandscape;
}
According to the ViewController Programming Guide for iOS, the autorotation is roughly controlled by the ViewController that was most recently made visible.
In your case that's probably the QLPreviewController itself, not your DocumentViewer. (And you say that the latter's shouldAutorotateToInterfaceOrientation: isn't called, which is consistent with this hypothesis).
So the autorotation is controlled by the shouldAutorotateToInterfaceOrientation: method of QLPreviewController, which in a little experiment of mine seems to allow everything but upside-down orientation.
So what you can do is define a subclass of QLPreviewController that only overrides shouldAutorotateToInterfaceOrientation: the way you did in DocumentViewer and use this subclass instead of the original QLPreviewController.
LandscapeOnlyQLPreviewController.h:
#import <QuickLook/QuickLook.h>
#interface LandscapeOnlyQLPreviewController : QLPreviewController {
}
#end
LandscapeOnlyQLPreviewController.m:
#import "LandscapeOnlyQLPreviewController.h"
#implementation LandscapeOnlyQLPreviewController
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
#end
I never did find a good answer, so I ended up just using a UIWebView.
But I'm still looking.
Try this:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}