I created a simple video player that when portrait it shows the video in a small window on top of the view but when switched to landscape it automatically switches to full screen.
A lot like the youTube app does.
My issue is that it doesn't transition well to the full screen mode. The navigation/tabbar controllers transition but my video just basically pops from one to the other.
Here's a little video of what's happening:
http://screencast.com/t/jaOoPOHLh
Here's the code I'm using to play the video and switch the orientation.
self.controller = [[LBYouTubePlayerController alloc] initWithYouTubeURL:[NSURL URLWithString:#"http://www.youtube.com/watch?v=1fTIhC1WSew&list=FLEYfH4kbq85W_CiOTuSjf8w&feature=mh_lolz"] quality:LBYouTubeVideoQualityLarge];
self.controller.delegate = self;
self.controller.view.frame = CGRectMake(0.0f, 0.0f, 320.0f, 180.0f);
- (void) orientationChanged:(NSNotification *)note
{
//self.controller.view.hidden = YES;
UIDevice * device = note.object;
switch(device.orientation)
{
case UIDeviceOrientationPortrait:
/* start special animation */
self.controller.fullscreen = NO;
//self.controller.view.hidden = NO;
break;
case UIDeviceOrientationPortraitUpsideDown:
/* start special animation */
break;
case UIDeviceOrientationLandscapeLeft:
// do something
//self.controller.fullscreen = YES;
//self.controller.scalingMode = MPMovieScalingModeAspectFit;
//self.controller.view.hidden = NO;
break;
case UIDeviceOrientationLandscapeRight:
self.controller.fullscreen = YES;
self.controller.scalingMode = MPMovieScalingModeAspectFit;
self.controller.view.hidden = NO;
break;
default:
break;
};
}
Is there something I need to add or custom transition I'm suppose to do to make the video transition and match the navigation/tabbar?
Related
I used openCV camera in my application. The OpenCV camera is working fine either in landscape left or landscape right. I set the orientation as below
-(void)initOpenCVCamera:(UIImageView*)imgView{
VideoCamera *vcamera = [[VideoCamera alloc] initWithParentView:imgView];
vcamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationLandscapeRight;
vcamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionBack;
vcamera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset640x480;
vcamera.delegate = self;
vcamera.recordVideo = NO;
vcamera.grayscaleMode = NO;
vcamera.rotateVideo = YES;
vcamera.defaultFPS = 30;
}
The default orientation set it to Landscape Right in the above code. But i wanted to support both landscape left and landscape right orientation. So i implemented the delegate methods of OpenCV camera as below
#interface VideoCamera : CvVideoCamera
- (void)updateOrientation;
- (void)layoutPreviewLayer;
#end
#implementation VideoCamera
- (void)updateOrientation
{
self->customPreviewLayer.bounds = CGRectMake(0, 0, self.parentView.frame.size.width, self.parentView.frame.size.height);
[self layoutPreviewLayer];
}
- (void)layoutPreviewLayer
{
if (self.parentView != nil)
{
CALayer* layer = self->customPreviewLayer;
CGRect bounds = self->customPreviewLayer.bounds;
int rotation_angle = 0;
switch (self.defaultAVCaptureVideoOrientation) {
case AVCaptureVideoOrientationLandscapeRight:
rotation_angle = 0;
break;
case AVCaptureVideoOrientationLandscapeLeft:
rotation_angle = 180;
break;
default:
break;
}
layer.position = CGPointMake(self.parentView.frame.size.width/2., self.parentView.frame.size.height/2.);
layer.affineTransform = CGAffineTransformMakeRotation( DEGREES_RADIANS(rotation_angle) );
layer.bounds = bounds;
}
}
#end
But it is not working. I don't know what is the "rotation_angle" i suppose to set.
I'm trying to add a UIWindow with UIWindowLevelStatusBar level. it works in portrait mode on ipad perfectly but after rotating device its messed up.
on iOS 7.x all rotations are fine except for upside-down, and on iOS 8.x only portrait mode is fine and all other orientations are messed up. any idea how to solve that?
CGRect frame = [UIApplication sharedApplication].statusBarFrame;
self.statusWindow = [[UIWindow alloc] initWithFrame:CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, 20)];
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect frame = [UIApplication sharedApplication].statusBarFrame;
CGAffineTransform test = [self transformForOrientation:orientation];
[self.statusWindow setWindowLevel:UIWindowLevelStatusBar];
[self.statusWindow setHidden:NO];
- (CGAffineTransform)transformForOrientation:(UIInterfaceOrientation)orientation
{
switch (orientation)
{
case UIInterfaceOrientationLandscapeLeft:
return CGAffineTransformMakeRotation(-DEGREES_TO_RADIANS(90.0f));
case UIInterfaceOrientationLandscapeRight:
return CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(90.0f));
case UIInterfaceOrientationPortraitUpsideDown:
return CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(180.0f));
case UIInterfaceOrientationPortrait:
default:
return CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0.0f));
}
}
In your UIWindow subclass' init method, observe this notification:
// Rotation Notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didChangeOrientation:) name:UIDeviceOrientationDidChangeNotification object:nil];
self.baseT = self.transform;
Then the method itself:
- (void)didChangeOrientation:(NSNotification *)n
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
switch (orientation) {
case UIInterfaceOrientationPortrait:
self.transform = CGAffineTransformRotate(self.baseT, 0);
break;
case UIInterfaceOrientationPortraitUpsideDown:
self.transform = CGAffineTransformRotate(self.baseT, M_PI);
break;
// Home button on left
case UIInterfaceOrientationLandscapeLeft:
self.transform = CGAffineTransformRotate(self.baseT, -M_PI_2);
break;
case UIInterfaceOrientationLandscapeRight:
self.transform = CGAffineTransformRotate(self.baseT, M_PI_2);
break;
default:
self.transform = CGAffineTransformMakeRotation(0);
break;
}
}
Depending on your implementation, you may have to also ensure the frame doesn't change. Also, in the Class' dealloc method, stop listening to the notifications.
As a modification to #dezinezync's answer: performing the rotation would work better if you put it in the willRotateToInterfaceOrientation method of the view controller. This way, the rotation will only be applied if the device is rotated to one of the supported orientations specified in the General -> Deployment Info section of the app's build settings. As an added bonus, you get access to the duration of the rotation animation. Just make sure you have a reference to your modal window in the view controller.
The UIDeviceOrientationDidChangeNotification notification is fired whenever the screen orientation changes, regardless of what orientations are supported. This can lead to undesireable behavior.
Here's an example:
UIWindow *modalWindow;
// Initialize your modal window somewhere in your code
// ...
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
// Make sure the modalWindow exists
if (modalWindow != nil)
{
// Animate the modal window's rotation
[UIView animateWithDuration:duration animations:^{
[self rotateModal:modalWindow];
}];
}
}
- (void)rotateModal:(UIWindow*)window
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
switch (orientation) {
case UIInterfaceOrientationPortrait:
window.transform = CGAffineTransformRotate(self.baseT, 0);
break;
case UIInterfaceOrientationPortraitUpsideDown:
window.transform = CGAffineTransformRotate(self.baseT, M_PI);
break;
// Home button on left
case UIInterfaceOrientationLandscapeLeft:
window.transform = CGAffineTransformRotate(self.baseT, -M_PI_2);
break;
case UIInterfaceOrientationLandscapeRight:
window.transform = CGAffineTransformRotate(self.baseT, M_PI_2);
break;
default:
window.transform = CGAffineTransformMakeRotation(0);
break;
}
}
I just did something like this on a landscape-only app, and I finally got it working properly by moving everything to the willRotateToInterfaceOrientation method.
Solution for iOS8 (need a transform as showed above as well):
UIScreen *screen = [UIScreen mainScreen];
CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
if ([screen respondsToSelector:#selector(fixedCoordinateSpace)])
{
[self setFrame:[screen.coordinateSpace convertRect:statusBarFrame toCoordinateSpace:screen.fixedCoordinateSpace]];
}
However it does not work for iOS9 beta.
I am using an UIImagePickerController within an UIPopoverController which is working perfectly with iOS6. With iOS 7 the "preview" image which is shown to capture the image is rotated, but if I take a picture it is saved correctly.
This is how I get my picker:
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage,
nil];
imagePicker.allowsEditing = NO;
And add it to a popover controller:
self.imagePickerPopOver = [[UIPopoverController alloc] initWithContentViewController:imagePicker];
[self.imagePickerPopOver presentPopoverFromRect:CGRectMake(aPosViewA.x, cameraButton_y, 100.0, 30.0) inView:self.detailViewController.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Those are calculations for the button position at a UIScrollView to show the popover at the correct position:
presentPopoverFromRect:CGRectMake(aPosViewA.x, cameraButton_y, 100.0, 30.0)
I don't think that the problem lies there as I have tried out several combinations.
I have also tried to capture the image in fullscreen-mode, but the app is only allowed to use landscape mode. If the image is taken in portrait-mode and the modal view is dismissed, the app stays in portrait mode as well. I couldn't find a way to prevent the UIImagePickerController to switch to portrait mode or to force the app back to landscape mode if the modal view was dismissed.
UPDATE
I have taken the answer from here and came a step further.
I transform the view after creating the picker and before showing the popover :
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationLandscapeLeft:
self.imagePicker.view.transform = CGAffineTransformMakeRotation(M_PI/2);
break;
case UIInterfaceOrientationLandscapeRight:
self.imagePicker.view.transform = CGAffineTransformMakeRotation(-M_PI/2);
break;
default:
break;
}
which works as long as i don't turn around the iPad. For that I am registering for the orientation changed event:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
and change the picker view:
- (void)orientationChanged:(NSNotification *)notification{
if (self.imagePicker) {
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationLandscapeLeft:
self.imagePicker.view.transform = CGAffineTransformMakeRotation(M_PI/2);
break;
case UIInterfaceOrientationLandscapeRight:
self.imagePicker.view.transform = CGAffineTransformMakeRotation(-M_PI/2);
break;
default:
break;
}
}
}
REMAINING PROBLEM:
As I wrote in the beginning, when the picture was taken, it was shown correctly to accept or dismiss it. This is now transformed as well. Somehow I need to know when the image is taken and transform it back.
AND, this is really a nasty hack and probably won't work with the next iOS Update. Has anybody an idea how to implement that in a cleaner way?
UPDATE 2
This was too nasty, I have found a cleaner solution which solves my problem but is not the answer to the initial question regarding an imagepicker in a popover controller, which is not recommended by Apple, but allowed.
I have subclassed now the UIImagePickerController like this:
#implementation QPImagePickerController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
#end
and I am using the imagepicker in fullscreen instead in a popover. Tested so far in iOS7.
The UIImagePickerController has a property called cameraViewTransform. Applying a CGAffineTransform to this will transform the preview image but will not transform the captured image which will therefore be correctly captured. I have the same problem that you describe and I solved it (for iOS7) by creating my camera controller and placing it in a popover as follows:
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
[imagePickerController setDelegate:self];
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
CGFloat scaleFactor=1.3f;
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationLandscapeLeft:
imagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * 90 / 180.0), scaleFactor, scaleFactor);
break;
case UIInterfaceOrientationLandscapeRight:
imagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * -90 / 180.0), scaleFactor, scaleFactor);
break;
case UIInterfaceOrientationPortraitUpsideDown:
imagePickerController.cameraViewTransform = CGAffineTransformMakeRotation(M_PI * 180 / 180.0);
break;
default:
break;
}
__popoverController = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];
[__popoverController presentPopoverFromRect:presentationRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
I also scale the image when in Landscape so that it fills the viewfinder more than it otherwise would. To my mind this is all rather nasty, but I will hopefully be able to remove it once iOS7.1 arrives.
I've found another solution which handles the case where a device is rotated while the UIIMagePickerView is presenting based on the answer Journeyman provided. It also handles the case where the view is rotated from UIOrientationLandscapeRight/UIOrientationLandscapeLeft back to UIOrientationPortrait.
I created a subclass of UIImagePickerController:
#import <UIKit/UIKit.h>
#interface PMImagePickerController : UIImagePickerController
#end
Then registered it to receive notifications if the device orientation changes:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(fixCameraOrientation:) name:UIDeviceOrientationDidChangeNotification object:nil];
The selector fixCameraOrientation contains Journeyman's code with one extra case, wrapped in a check to make sure the sourceType is the camera:
- (void)fixCameraOrientation:(NSNotification*)notification
{
if (self.sourceType == UIImagePickerControllerSourceTypeCamera) {
CGFloat scaleFactor=1.3f;
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationLandscapeLeft:
self.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * 90 / 180.0), scaleFactor, scaleFactor);
break;
case UIInterfaceOrientationLandscapeRight:
self.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * -90 / 180.0), scaleFactor, scaleFactor);
break;
case UIInterfaceOrientationPortraitUpsideDown:
self.cameraViewTransform = CGAffineTransformMakeRotation(M_PI * 180 / 180.0);
break;
case UIInterfaceOrientationPortrait:
self.cameraViewTransform = CGAffineTransformIdentity;
break;
default:
break;
}
}
}
The important case here is the case where the device orientation goes to portrait. The overlay's view needs to be reset in this case. It's also important for the fixCameraOrientation selector to be called after the image picker view loads, in case the device is rotated:
- (void)viewDidLoad
{
[super viewDidLoad];
[self fixCameraOrientation:nil];
}
I had a similar situation in my app. However the preview was rotating correctly in iOS7 and not in iOS8. This code assumes you have more than one orientation.
The first thing is to subclass UIImagePickerController.
Starting from the top, add #import <AVFoundation/AVFoundation.h> to your .m file.
Also add a property to save the initial orientation #property (nonatomic) UIInterfaceOrientation startingOrientation; and another for a condition to remove clipping #property (nonatomic) BOOL didAttemptToRemoveCropping;.
Were going to listen to a couple of notifications.
UIApplicationDidChangeStatusBarOrientationNotification is obviously to listen for the device rotation. AVCaptureSessionDidStartRunningNotification is called right when the camera starts capturing.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(statusBarOrientationDidChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(captureSessionDidStart:) name:AVCaptureSessionDidStartRunningNotification object:nil];
In the -captureSessionDidStart: add a condition to verify the view is actually on screen and to make sure the camera is supposed to be displayed if (self.view.window && self.sourceType == UIImagePickerControllerSourceTypeCamera). If so, set the starting orientation self.startingOrientation = [UIApplication sharedApplication].statusBarOrientation;.
In the -statusBarOrientationDidChange: add the same condition as above, but this time if true, we'll update the camera transform. First we get the offset rotation based on the initial rotation. This is needed when you enter the UIImagePickerController in orientations other then portrait.
CGFloat startingRotation = ({
CGFloat rotation;
switch (self.startingOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
rotation = M_PI;
break;
case UIInterfaceOrientationLandscapeLeft:
rotation = -M_PI_2;
break;
case UIInterfaceOrientationLandscapeRight:
rotation = M_PI_2;
break;
default:
rotation = 0.0f;
break;
}
rotation;
});
Next we'll update the camera transform with the current rotation.
self.cameraViewTransform = CGAffineTransformMakeRotation(({
CGFloat angle;
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
angle = startingRotation + M_PI;
break;
case UIInterfaceOrientationLandscapeLeft:
angle = startingRotation + M_PI_2;
break;
case UIInterfaceOrientationLandscapeRight:
angle = startingRotation + -M_PI_2;
break;
default:
angle = startingRotation;
break;
}
angle;
}));
And finally we'll attempt to remove the black bars presented in either 90 degree orientation from the starting orientation. (This might only be an iOS8 issue.) In slightly more detail, if I enter the UIImagePickerController in portrait mode and then rotate to landscape, there will be black bars on the top and bottom of the preview. The solution for this is not to scale but rather to remove the clipping of a superview. We only need to make this attempt once, so first check if we have called this code. Also make sure that we only call this code if we have rotated. If its called in the initial orientation it wont work right away.
if (!self.didAttemptToRemoveCropping && self.startingOrientation != [UIApplication sharedApplication].statusBarOrientation) {
self.didAttemptToRemoveCropping = YES;
[self findClippedSubviewInView:self.view];
}
Finally in the code for -findClippedSubviewInView: we loop through all the subviews to search for a view with .clipsToBounds = YES. If thats true we make one more condition to verify one of its ancestral superviews is correct.
for (UIView* subview in view.subviews) {
if (subview.clipsToBounds) {
if ([self hasAncestorCameraView:subview]) {
subview.clipsToBounds = NO;
break;
}
}
[self findClippedSubviewInView:subview];
}
In the -hasAncestorCameraView: we simply loop up the superview chain and return true if one of the classes has CameraView in the name.
if (view == self.view) {
return NO;
}
NSString* className = NSStringFromClass([view class]);
if ([className rangeOfString:#"CameraView"].location != NSNotFound) {
return YES;
} else {
return [self hasAncestorCameraView:view.superview];
}
Thats the breakdown of code, here's it all together.
#import <AVFoundation/AVFoundation.h>
#import "GImagePickerController.h"
#interface GImagePickerController ()
#property (nonatomic) UIInterfaceOrientation startingOrientation;
#property (nonatomic) BOOL didAttemptToRemoveCropping;
#end
#implementation GImagePickerController
- (instancetype)init {
self = [super init];
if (self) {
if ([[[UIDevice currentDevice] systemVersion] intValue] >= 8) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(statusBarOrientationDidChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(captureSessionDidStart:) name:AVCaptureSessionDidStartRunningNotification object:nil];
}
}
return self;
}
- (void)dealloc {
if ([[[UIDevice currentDevice] systemVersion] intValue] >= 8) {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
#pragma mark - Capture Session
- (void)captureSessionDidStart:(NSNotification *)notification {
if (self.view.window && self.sourceType == UIImagePickerControllerSourceTypeCamera) {
[self updateStartingOrientation];
}
}
#pragma mark - Orientation
- (void)updateStartingOrientation {
self.startingOrientation = [UIApplication sharedApplication].statusBarOrientation;
[self updateCameraTransform];
}
- (void)updateCameraTransform {
CGFloat startingRotation = ({
CGFloat rotation;
switch (self.startingOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
rotation = M_PI;
break;
case UIInterfaceOrientationLandscapeLeft:
rotation = -M_PI_2;
break;
case UIInterfaceOrientationLandscapeRight:
rotation = M_PI_2;
break;
default:
rotation = 0.0f;
break;
}
rotation;
});
self.cameraViewTransform = CGAffineTransformMakeRotation(({
CGFloat angle;
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
angle = startingRotation + M_PI;
break;
case UIInterfaceOrientationLandscapeLeft:
angle = startingRotation + M_PI_2;
break;
case UIInterfaceOrientationLandscapeRight:
angle = startingRotation + -M_PI_2;
break;
default:
angle = startingRotation;
break;
}
angle;
}));
if (!self.didAttemptToRemoveCropping && self.startingOrientation != [UIApplication sharedApplication].statusBarOrientation) {
self.didAttemptToRemoveCropping = YES;
[self findClippedSubviewInView:self.view];
}
}
- (void)statusBarOrientationDidChange:(NSNotification *)notification {
if (self.view.window && self.sourceType == UIImagePickerControllerSourceTypeCamera) {
[self updateCameraTransform];
}
}
#pragma mark - Remove Clip To Bounds
- (BOOL)hasAncestorCameraView:(UIView *)view {
if (view == self.view) {
return NO;
}
NSString* className = NSStringFromClass([view class]);
if ([className rangeOfString:#"CameraView"].location != NSNotFound) {
return YES;
} else {
return [self hasAncestorCameraView:view.superview];
}
}
- (void)findClippedSubviewInView:(UIView *)view {
for (UIView* subview in view.subviews) {
if (subview.clipsToBounds) {
if ([self hasAncestorCameraView:subview]) {
subview.clipsToBounds = NO;
break;
}
}
[self findClippedSubviewInView:subview];
}
}
#end
iPad with Camera - don't display in a popover. Instead, present in a modal view controller, like you would on the iPhone. (at least starting with iOS 7)
I am trying to add an image view to my application window which consists of a splitviewcontroller. The reason I am doing this is so that I can fade it out like a splash screen. The application is for iPad and only works in the landscape mode. The launch image is the same as the splash image so it is a seamless transition between the two, then I can manually fade out the splash. However I am having trouble adding the splash to the window's subview in the same orientation as the launch image so that the transition from the launchimage to the splash is seamless and cannot be noticed. Here is what I have so far:
- (void)viewDidLoad
{
[super viewDidLoad];
UIWindow *window = [[UIApplication sharedApplication] delegate].window;
UIImageView *splash = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
splash.image = [UIImage imageNamed:#"Default-Landscape~ipad.png"];
[splash rotateToInterfaceOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
[window addSubview:splash];
}
#interface UIView (Orientation)
- (void)rotateToInterfaceOrientation:(UIInterfaceOrientation)orientation;
#end
#implementation UIView (Orientation)
- (void)rotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
{
CGFloat angle = 0.0;
switch (orientation) {
case UIInterfaceOrientationPortraitUpsideDown:
angle = M_PI;
break;
case UIInterfaceOrientationLandscapeLeft:
angle = - M_PI / 2.0f;
break;
case UIInterfaceOrientationLandscapeRight:
angle = M_PI / 2.0f;
break;
default: // As portrait
angle = 0.0;
break;
}
self.transform = CGAffineTransformMakeRotation(angle);
}
#end
I am working on a universal application that starts with a really short intro video. So I simply add a MPMoviePlayerViewController and modally present it. On the iPhone everything works fine even if I play the video in landscape mode. But on the iPad the video always plays in portrait mode no matter what interface orientation the device currently has. I searched for hours and tried a lot of different things like CGAffineTransformation or adding a new view, but nothing seems to work. Here is the code that I work with:
NSString *filePath = [[NSBundle mainBundle] pathForResource:videoName ofType:#"mp4"];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
self.startupController = [[MPMoviePlayerViewController alloc] initWithContentURL:fileURL];
[self.startupController.moviePlayer setControlStyle:MPMovieControlStyleNone];
[self.startupController.moviePlayer setScalingMode:MPMovieScalingModeAspectFit];
[self.startupController.moviePlayer setFullscreen:YES];
[self presentModalViewController:self.startupController animated:NO];
Do you have any idea how I can fix this issue? In my opinion this should be a simple feature offered by Apple, but sometimes the easiest things are the ones I have to worry about most...
Here is how I did it.
First, listen to this notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(detectOrientation) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
Then implement this :
- (void)detectOrientation {
NSLog(#"handling orientation");
[self setMoviePlayerViewOrientation:[[UIDevice currentDevice] orientation]];
}
- (void)setMoviePlayerViewOrientation:(UIDeviceOrientation)orientation {
if (lwvc != nil)
return;
if (moviePlayerController.playbackState == MPMoviePlaybackStateStopped) return;
//Rotate the view!
CGFloat degree = 0;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.1];
switch (orientation) {
case UIDeviceOrientationPortrait:
case UIDeviceOrientationPortraitUpsideDown:
degree = 0;
moviePlayerController.view.bounds = CGRectMake(0, 0, 320, height);
break;
case UIDeviceOrientationLandscapeLeft:
degree = 90;
moviePlayerController.view.bounds = CGRectMake(0, 0, height, 320);
break;
case UIDeviceOrientationLandscapeRight:
degree = -90;
moviePlayerController.view.bounds = CGRectMake(0, 0, height, 320);
break;
default:
break;
}
lastOrientation = orientation;
CGAffineTransform cgCTM = CGAffineTransformMakeRotation((degree) * M_PI / 180);
moviePlayerController.view.transform = cgCTM;
[UIView commitAnimations];
[[UIApplication sharedApplication] setStatusBarOrientation:orientation];
}
So the trick is just using transformation