Prevent MPMoviePlayerController rotating and scaling to portrait when in fullscreen - ios

In an iOS5 application for iPhone 4/4s I have a UIViewController with an MPMoviePlayerController view added to its view:
[self.view insertSubview:self.fullscreenMoviePlayerController.view atIndex:2];
The UIViewController only supports landscape orientation:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation
{
// Return YES for supported orientations.
return interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight;
}
this correctly locks rotation to only landscape. However when I set the MPVideoPlayerController to display fullscreen, this is ignored and the video is no longer constrained to landscape and rotates to whatever orientation the phone is held in.
How can I prevent MPMoviePlayerController's video from rotating to Portrait orientations in fullscreen? It is crucial that the video does not rotate when the phone is rotated to portrait.
I have tried subclassing MPVideoPlayerController and overriding shouldAutorotateToInterfaceOrientation: but this has no effect.
The MPMoviePlayerController is only one part of the view, so using an MPMoviePlayerViewCotroller is absolutely not an option.

This seems to be rather difficult if you really want to avoid using MPMoviePlayerViewController.
One option, that seems to work even if you have it in fullscreen, is to manually set the frame of the MPMoviePlayerController's view.
(Note that in other iOS issues, sometimes using the background view has produced different results, but it's worth a shot).
MyMPMoviePlayerController.view.frame = CGRectMake(0, 0, your numbers, here);
However, Apple, in their docs, says that the controller's frame should be set to the frame of it's parent view.
[MyMPMoviePlayerController.view setFrame: parentView.bounds];
The less elegant solution, but one that might work even if that one doesn't is this:
Listen for the UIDeviceOrientationDidChangeNotification and take the movie player's view. Apply a transfrom, bounds, and center (or frame, etc) on it so that it still fits in the landscape view. Essentially transform it back each time it tries to rotate away. (This is all assuming that you really cannot keep it from rotating with shouldAutorotateToInterfaceOrientation:).
The only issue here is that it may keep the movie in portrait but screw around with the view, which is not the desired outcome.

yes, i saw you said using MPMoviePlayerViewController is not an option:
still … why not attempt to make MPMoviePlayerViewController of the ViewController that you have that otherwise contains the MPMoviePlayerController and the other items in your view controller. the good part about this is that MPMoviePlayerViewController already has the MPMoviePlayerController built in. you just refer to that instead of the MPMoviePlayerController that you have in your own viewController. that has the shouldAutorotateToInterfaceOrientation that you can override and should do the right thing for you.

You can prepare two videos. If there is no other choice.

Please Visit the link this shows the video only in the landscape mode by default it does so http://mobiledevelopertips.com/video/getting-mpmovieplayercontroller-to-cooperate-with-ios4-3-2-ipad-and-earlier-versions-of-iphone-sdk.html. I hope it will resolve your problem.

Related

Rotate a single view to landscape in a portrait locked Application in iOS 8

I have an application that uses portrait mode in the the view controllers except for one, that one page needs to be landscape only (landscape left or landscape right). How can I achieve that ?
I tried multiple solutions that say set the orientation mode for the Navigation Bar and the Application will turn but unfortunately that doesn't work for me. Also I tried manually rotating the view, it worked but when I click the text field to write something in it, the keyboard appears in the portrait mode rather than the landscape one.
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
the above code works for me but only when I allow the app to rotate in landscape and portrait both but this is not what I want because this way all the pages can turn landscape from portrait.
EDIT:
My situation here is that I have been assigned with an already made project. The guy who has made this app had been using STNavigation Manager (i'm not exaclty sure what that is) rather than self.navigationController push and pop as stuff. So shouldAutoRotate and these delegates are not working in my app. Secondly he has also disabled the navigationBar and created his own NavigationBar.
If you enable the landscape modes you need in the application you can use the code you are using to force the app into the landscape mode you want and then force it back to portrait before you return to the screen in which you want to be portrait.
I found the best way is to create a subclass of UINavigationController that disallows rotation via
-(BOOL)shouldAutoRotate
Then in the one view i want landscape implementing the same method on the VC level returning true.
Use UIView's transform property to rotate:
-(void)viewWillAppear:(BOOL)animated
{
CGAffineTransform newTransform = CGAffineTransformMake(0.0,1.0,-1.0,0.0,0.0,0.0);
self.view.transform = newTransform;
}

iOS change screen orientation on demand

I have an app with an UITableView at the home screen. I made this view to always be in landscape orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
If the user picks a row he will be taken to a UIPageViewController view. This second view can rotate to landscape and portrait. The problem is when I am in portrait mode on the UIPageViewController and I press the go back button, the first view which is supposed to be always in landscape mode now is in portrait. After I rotate it, it gets into landscape and stays there.
I was wondering maybe if there is a way to make my home screen go automatically into landscape when I go back to it.
Try the following
Create the view of your main screen in app in interface builder in Landscape mode.
Create uiview oultlet in interface class and connect it to above view.
IBOutlet UIVIew *myView;
Then in the viewDidLoad method set this
self.view = self.myView;
If you want to make a screen in a particular orientation then you can create a CustomNavigation controller and then present it in your app. You have to only return supportedInterfaceOrientations in this. If you want more detail and sample code click here.
Call shouldAutorotateToInterfaceOrientation manually when you go back. You can not force a "real" orientation change, that's a OS thing.
As said in the view controller programming guide, you can have a alternate landscape interface and before coming to home screen from any other view, you can check the orientation and push the corresponding interface onto the screen
Read this SO question and answer for better understanding of launching an app in landscape.Also go through above apple programming guide which i pointed to.
If you use the UINavigationViewController methods(pushViewController:animated: and popViewControllerAnimated:), the views will inherit the previous view's orientation.
On the other hand, if you use presentModalViewController:animated: and dismissModalViewControllerAnimated: methods, everything works perfectly. Hope this helped!
Use this, change the UIInterfaceOrientationLandscapeLeft to required orientation type as UIDeviceOrientationPortrait, UIDeviceOrientationLandscapeLeft etc.
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];

How do I make sure my view is oriented properly after full screen video?

I've got a universal ipad/iphone app that allows the user to watch a video, which they can then expand into full screen mode.
I have implemented (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration, and in that method I perform various setFrame calls on my view elements depending on whether they are in landscape or portrait orientation.
That all seems to work fine in normal use, i.e. rotating back and forth works fine.
But if the user starts in portrait mode, starts a video, goes to full screen mode, turns into landscape orientation, and then the video stops -- the elements are often not resized properly. They appear to be sized still as if they are portrait mode.
If I then turn to portrait mode, and then turn back to landscape, the view resets correctly.
The strange part is, I have implemented (void)exitedFullscreen:(NSNotification*)notification and in there I print out the orientation, and it's seen correctly. I also call my code to reset the view elements based on the current orientation, and I am still having this problem.
Another related issue is sometimes when dealing with rotation, my views will end up too far up the screen, actually going under the status bar at the top of the device.
Edit Here's the latest example. I rotate to landscape mode during full screen video playback, and then when I left full screen video, you can see the issue with the navigation bar at the top of the view.
One possible way to solve this is by presenting your view controller modally instead of using the navigation view controller.
Refer to Kenny's answer at Problem pushViewController from Landscape to Portrait
Your ViewController might not be rotating because another controller is the first responder. What you can do to avoid this is register the view controller to the device rotation changes and implement the rotation in the selector you call when you receive such a notification.
In appDelegate:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
In your view controller
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didRotate:)name:UIDeviceOrientationDidChangeNotification object:nil];
In did rotate you can check the orientation with
[[UIDevice currentDevice] orientation]
The navigation bar at the top of the view. I solved it, using this code ->
[[UIApplication sharedApplication] setStatusBarHidden:NO animated:NO];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault animated:YES];
Using this after your rotation.
Mason, did you logged and checked whether your method willAnimateRotationToInterfaceOrientation:duration: gets called after each state transition?
To me this latest screenshot does not look like an orientation change issue.
The navigation bar is basically off by the status bar's height.
Possibly your position calculation fails because you are using the view's frame
while the fullscreen video (w/o status bar) is playing and this fails as soon as
the statusbar is back?
Your orientation may not get updated properly if there is another controller acting as a first responder. The best way to overcome this is to call the functions you use to orientate the screen at the method viewWillAppear: using the current orientation of the view controller: [self interfaceOrientation]
If you use a subclassed subview you may need to reimplement the methot layoutSubviews and call setNeedsLayout. Another thing that may be causing this is resigning the viewcontroller where you have the video as first responder (you mays search if somewhere you use the methon resignfirstresponder and try how it works without it). If this does not work, I don't know, this things may be very tricky and dependent on how you have implemented it. But for the things you say you do you should not need much code, since automatic rotation and resizing of views is handled now by the sizes inspector of the views editor.
I think that this should do.

iPad app landscape launches root view controller with portrait dimension

I have setup a new iPad project to only support UIInterfaceOrientationLandscapeRight.
In my App Delegate I add a RootViewController to the window's rootViewController.
In this UIViewController (RootViewController) I have the following:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
I have also tried with:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
However, I am not able to get the correct dimensions for my app when I create and add subviews based on the dimensions of my view controller's view.
If I output self.view.frame for my view controller I get {{0, 0}, {768, 1024}}, but I would like {1024, 768} instead. If I can't when are the dimensions correct so I can create my views with them in mind?
Sorry if this has been asked a billion times, I've browsed lots of SO questions, but nothing has solved my issue.
I was running into the same issue, and what Ash Furrow said above seems to be correct; the orientation is set after viewDidLoad is called.
I was creating an iPad app that works in all orientations, but only the portrait orientations were getting set up correctly in my root UIViewController. In order to make the views layout correctly in landscape, I had to make sure the autoresizing masks on all my subviews was set to allow the view to adjust to landscape behind the scenes before being displayed to the user.
For example, I had a UIImageView that was the same size as the UIViewController's UIView. In order to get it to adjust correctly when rotating to landscape:
UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
backgroundImageView.autoresizingMask = (UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight);
[self.view addSubview:backgroundImageView];
Now the UIViewController can be configured in portrait orientation in the viewDidLoad method and rotate nicely to the portrait orientation before being displayed to the user.
EDIT:
Looks like the interface orientation is being set already in viewDidLoad
p (UIInterfaceOrientation)[self interfaceOrientation]
(UIInterfaceOrientation) $1 = UIInterfaceOrientationLandscapeRight
Here's my theory: interfaces on the iPad are, by default, 1024x768 if that have a status bar, which yours does. I believe that, even though the interface orientation is correct, it's not updating the view geometry until after viewDidLoad. I believe it has a very good reason for that.
If you look at the UIViewController Life Cycle docs, viewDidLoad is called as part of the set up of the view controller. After the view is loaded, willAnimateRotationToInterfaceOrientation: duration: is called to let your view controller know it's geometry is changing.
It's not so much an answer as an explanation. Hopefully this will help you architect a solution to get around this problem.
Begin answer that doesn't actually work:
In the info.plist for your project, open the "Supported Interface Orientations" option and delete the interface orientations you don't want to support. By default, all are supported:
That should clear it up.
I have a simple solution: the Apple default app templates work with XIBs for the main view controller. To solve your problem just open the main viewcontroller XIB and set orientation to "landscape".
As I usually don't use XIBs and create all UI elements programmatically. That's why I had the same problem in previous projects that really drove me crazy. I then solved it by hard-coding the frame width & height value - not the nice way.

UIWebview -- "Open/Copy" dialog opens in wrong orientation

I'm doing some fancy stuff with rotation, and am returning NO from shouldAutorotateToInterfaceOrientation:. I then manually rotate a UIWebView according to [UIDevice currentDevice].orientationCached. When I hold my finger down on a link, the menu which appears is always in PortraitLeft orientation, no matter how the device is actually oriented, and no matter how the UIWebView is oriented.
It looks to me like the link menu takes its orientation from the main view of the view controller, rather than the UIWebView its associated with, and that the only way to get it to behave correctly is to return YES from -shouldAutorotateToInterfaceOrientation:.
Is this assumption correct? Is there any way to control the orientation of the link-related popup menu, or to force it to take its orientation from the UIWebView which spawns it?
I wouldn't actually set the orientation manually how you're doing it in the UIWebView. Instead, force the orientation of the parent view controller through code.
As an example of a similar situation, I have an app that I've developed that displays a map in a few views. When rotated from portrait to landscape, it layouts the view in a very different manner from the portrait layout with a fancy animation. I like it, but some users don't, so I provide the option to disable map rotation. And I do that by passing in only certain rotation abilities to the parent view. So if they disable landscape, I tell the parent view controller it can only rotate to landscape. Otherwise, it's free to rotate to any orientation except upside down.
Enough with the explanation: here's my relevant code I use to accomplish this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
//Rotate the view if rotation is actually enabled
if ([self.prefs boolForKey:#"SHOULD_ROTATE"]) {
return (UIInterfaceOrientationIsLandscape(toInterfaceOrientation) || UIInterfaceOrientationPortrait == toInterfaceOrientation);
}
//Rotate it to portrait only if rotation is disabled
else if (![self.prefs boolForKey:#"SHOULD_ROTATE"]) {
return (UIInterfaceOrientationPortrait == toInterfaceOrientation);
}
//Otherwise, rotate only to portrait (for all views minus the map views)
else {
return (UIInterfaceOrientationPortrait == toInterfaceOrientation);
}
}
I actually implement this in the UITabBarController so that it applies to all views and view controllers in the app, but it's just as easily implemented only for the UIWebView parent view controller. The gist is that you're returning yes or no based on if the view orientation matches what you want it to. For the web view, you would want to lay out the only allowed rotation orientations to by returning this:
return (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)
Of course, I haven't discussed forcing the view to set the view to a landscape view, only what it does once a user turns it. So the best course of action there is simply to manually do it once the view is initialized:
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO]
You'll have to set it to either Left or Right to start with, but the user can rotate between right and left as they wish if you implement my earlier code as well.
That's a lot of explanation, but I think the combination of these two methods for the parent view controller should allow you to present the view exactly how you wish. Let me know if you have any questions!
By "popup menu", do you mean the Action Sheet with Open … Copy buttons?
If so, then yes, Action Sheet always presents itself according to the top view controller's interfaceOrientation. Because you are rotating the view yourself without its controller updating its interfaceOrientation, the Action Sheet still thinks it is portrait.

Resources