iPhone - allow landscape orientation on just one viewcontroller - iphone

I have a navigation-based application in which I would like just one of the viewcontrollers to support landscape orientation. For that viewcontroller (vc1), in shouldAutorotate, I am returning YES for all orientations and in the other controllers I am returning YES only for portrait mode
But even then if the device is in landscape mode and I go to the next screen from vc1, the next screen also comes up rotated in landscape mode. I assumed that if I return a YES only for portrait mode, the screen should show up only in portrait.
Is this the expected behavior? How do I achieve what I am looking for?
Thanks.

You can't support the landscape orientation only for one of the viewcontrollers if you use shouldAutorotateToInterfaceOrientation method of UIViewController.
You have only two choice whether all viewcontrollers support the landscape or no viewcontrollers support it.
If you want to support the landscape only for one, You need to detect device rotation and manually rotate views in the viewcontroller.
You can detect the device rotation by using Notification.
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
Then, you can rotate your views when you detect the device rotation.
- (void)didRotate:(NSNotification *)notification {
UIDeviceOrientation orientation = [[notification object] orientation];
if (orientation == UIDeviceOrientationLandscapeLeft) {
[xxxView setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
} else if (orientation == UIDeviceOrientationLandscapeRight) {
[xxxView setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
} else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
[xxxView setTransform:CGAffineTransformMakeRotation(M_PI)];
} else if (orientation == UIDeviceOrientationPortrait) {
[xxxView setTransform:CGAffineTransformMakeRotation(0.0)];
}
}

I have also situation when I need all view controllers in portait mode, but one of them also can rotate to landscape mode. And this view controller has navigation bar.
For this purpose I have created second window, in my case it was camera view controller. And when I need to show camera view controller, I show camera window and hide when I need to push another view controller.
And you also need to add this code to AppDelegate.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if (window == self.cameraWindow)
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
return UIInterfaceOrientationMaskPortrait;
}

As i worked out for my App i advise you to use this solution.By using some conditions in the shouldAutorotateToInterfaceOrientation method orientation type we can solve this.Just try with this link will help you.
https://stackoverflow.com/questions/12021185/ios-rotate-view-only-one-view-controllers-view/15403129#154031

Related

iOS 6 landscape orientation problems

In iOS, after dismissing a modal view controller (which is being forced to only show in portrait orientation), if the device is being held in landscape mode, the view controller which presented the modal view controller doesn't rotate back to landscape correctly.
The 'willAnimateRotationToInterfaceOrientation' method gets called so I can manage rotation of my subviews etc. but then the actual view controller doesn't rotate to landscape. So my subviews look like they should in landscape, but the interface is in portrait mode.
The annoying thing is that it works fine in the iOS 5 simulator. Ie. After dismissing the modal view controller, the presenting view controller rotates back to landscape orientation.
Has anyone experienced something similar, or have any idea how to approach this?
For IOS 6 u need to handle the orientation with this methods.
- (BOOL)shouldAutorotate; {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations; {
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
}
else{
return UIInterfaceOrientationMaskLandscape;
}
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation; {
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
return UIInterfaceOrientationPortrait;
}
else{
return UIInterfaceOrientationLandscapeLeft;
}
}

Iphone landscape and portrait issue

I m working on one application in which i have splash screen and home screen. My Application is landscape and portrait mode application. When my application starts and i am on Landscape mode my home screen shows portrait mode for some mili seconds and after that it comes into the landscape mode. I want it should directly show the view in landscape mode.
Thanks
I usually enable notifications:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
On my controllers i put:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self configureOrientation:toInterfaceOrientation];
}
- (void)configureOrientation:(UIInterfaceOrientation)orientation
{
if(UIDeviceOrientationIsValidInterfaceOrientation(orientation)){
if(UIInterfaceOrientationIsLandscape(orientation)){
[self configureLandscapelView];
}else if(UIInterfaceOrientationIsPortrait(orientation)){
[self configurePortraitlView];
}
}
}
You can also get the orientation from the UIViewController itself:
UIInterfaceOrientation orientation = [self interfaceOrientation];
Or from the status bar:
[UIApplication sharedApplication] statusBarOrientation]

iPhone cannot rotate movie to landscape mode using MPMoviePlayerViewController

[update]
As was recommended I changed all the parent view controllers to support all orientations. My app structure is as follows: AppDelegate > RootViewController > Videos > VideoDetails > MPMoviePlayerViewController.
The video will play in landscape if I change all these to support all orientations. But supporting all orientations is not what I want and causes other issues. Is there any other work around or anything else I can do?
Thanks
[/update]
I have an portrait based iPhone app that displays videos using a custom subclass of MPMoviePlayerViewController. When the user presses play I create an instance of this class and present it modally as follows:
- (IBAction) playPressed:(id)sender {
NSString *filepath = [[NSBundle mainBundle] pathForResource:self.currentVideoModel.videoFileName ofType:#"m4v"];
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
// MovieViewController is just a simple subclass of MPMoviePlayerViewController
self.moviePlayerController = [[MovieViewController alloc] initWithContentURL:fileURL];
// full screen code.
[self.moviePlayerController.moviePlayer setScalingMode:MPMovieScalingModeFill];
[self.moviePlayerController.moviePlayer setFullscreen:TRUE];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlaybackComplete:) name:MPMoviePlayerPlaybackDidFinishNotification object:self.moviePlayerController];
[self presentMoviePlayerViewControllerAnimated:self.moviePlayerController];
}
The problem is that it plays fine in portrait but when I turn the iPhone to landscape the video still plays in portrait and not landscape :( All the view controllers in the app only support portrait orientation.
My MPMoviePlayerViewController subclass only overrides the following method to allow for orientation changes but it has no affect:
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return (toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight || toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
I've even tried to programmatically rotate the video but with absolutely no luck, it always stays in portrait mode.
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
[self.view setTransform:CGAffineTransformMakeRotation(M_PI / 2)];
return true;
}
else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
[self.view setTransform:CGAffineTransformMakeRotation(M_PI * 2)];
return true;
}
else if (toInterfaceOrientation == UIInterfaceOrientationPortrait) {
[self.view setTransform:CGAffineTransformIdentity];
return true;
}
else return false;
}
[EDIT] The below solution worked perfectly on iOS5 but no longer works on iOS6. I may get some time to look into this issue in the future hopefully :( [/EDIT]
OK I fixed it. It was all to do with my mis-understanding of how iOS notifies an app of orientation changes. I thought it broadcasts out any orientation change but it doesn't, it follows your view hierarchy and it is up to you to tell any child view controllers of an orientation change. This was my undoing.
My app consisted of the following set up:
window > RootViewController > tabbar controller > nav controller > view controller > MPMoviePlayerViewController
I subclassed the tabbar controller to only return true for portrait mode. I returned this from the root view controllers shouldAutoRotateToOrientation method. This ensured that all views will be portrait only.
Then I presented the movie modally using the presentMoviePlayerViewControllerAnimated method called from the RootViewController. This automatically called the custom MPMoviePlayerViewController's shouldAutoRotateToOrientation method which was set to YES for both landscape and portrait :)

Reverting to portrait after Done pressed on movie player?

I've got a MPMoviePlayer working. It is designed to show a postage-stamp size movie as a subview in the view. When the phone is rotated into landscape, it goes into full screen mode. And when the phone is in portrait it goes into postage-stamp portrait mode.
The only problem is when I press Done when in landscape mode, it stays in landscape, with the postage stamp sized movie, rather than kick back into portrait..
Here's some of my code:
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight || toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
[moviePlayerController setFullscreen:YES animated:YES];
} else
{
[moviePlayerController setFullscreen:NO animated:YES];
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationLandscapeLeft;
}
How would I get it to kick into portrait mode after pressing Done?
#cannyboy...you just need to use below method in your APPDelegate.m if your application only works with portrait mode
- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if ([[window.rootViewController presentedViewController] isKindOfClass:[MPMoviePlayerViewController class]])
{
//NSLog(#"in if part");
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else
{
//NSLog(#"in else part");
return UIInterfaceOrientationMaskPortrait;
}}
I was the same problem and now I am telling you how I solved it. I don't know the below method is right or wrong but it work fine.
Instead of opening MPMoviePlayer in view open it in a new viewController. I mean create a new UIViewController to show the movie and push it some how so that user will not understood that they are redirecting into a new screen.
Disable the parent screen for landscape mode and allow MovieViewController to landscape.
When user press the done button or close button simply pop the viewController and as the previous screen don't support landscape mode so the screen will automatically shows in portrait mode.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(_moviePlayerWillExitFullscreen:)
name:MPMoviePlayerWillExitFullscreenNotification object:nil];
- (void)_moviePlayerWillExitFullscreen:(NSNotification *)notification
{
CGFloat ios = [[[UIDevice currentDevice] systemVersion] floatValue];
CGFloat min = 5.0;
if (ios >= min)
{
if (self.interfaceOrientation != UIInterfaceOrientationPortrait)
{
if([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortrait])
{
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
[self willRotateToInterfaceOrientation:self.interfaceOrientation duration:0];
[UIViewController attemptRotationToDeviceOrientation];
}
}
}
}
Note that this only works in ios 5.0 and later, and you will get a warning that setOrientation is not supported, but it works pretty well
One way you could try is to force your device to think it is in portrait mode. To do this, try using:
[[UIDevice currentDevice] setOrientation:UIDeviceOrientationPortrait];
If you do not want your device to show landscape while not playing a movie, you will also have to add some logic to your code that you have shown above to only change to landscape if the movie is playing.

Xcode can't change back to landscape from portrait automatically

I have an iPhone app in which the RootViewController instance starts out in the landscape mode. It supports camera so it changes to portrait mode to take a photo. Once done it comes back to the RootViewController instance but the orientation doesn't change to landscape. I want this to automatically shift to the landscape orientation.
I tried adding
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]
in viewWillAppear method of RootViewController or viewWillDisapper of CameraViewController but orientation doesn't change. How do I programmatically change the orientation?
Try implementing following method in your controller.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if((interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight))
return YES;
return NO;
}
Hope it helps.