Forcing landscape orientation on fullscreen MPMoviePlayerController prevents correct rotation when exiting fullscreen
Asked Answered
A

8

14

I have an iPhone application (iOS6+) that supports all interface orientations. However, only landscape orientation should be supported when an MPMoviePlayerController is playing a video fullscreen.

I found the following solution on Stack Overflow and it works.

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerWillEnterFullscreenNotification:) name:MPMoviePlayerWillEnterFullscreenNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerWillExitFullscreenNotification:) name:MPMoviePlayerWillExitFullscreenNotification object:nil];

...

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    if (self.landscapeOnlyOrientation) {
        return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
    }
    return UIInterfaceOrientationMaskAll;
}

- (void)moviePlayerWillEnterFullscreenNotification:(NSNotification*)notification {
    self.landscapeOnlyOrientation = YES;
}

- (void)moviePlayerWillExitFullscreenNotification:(NSNotification*)notification {
    self.landscapeOnlyOrientation = NO;
}

However, an annoying problem persists, namely that if the video exits fullscreen in portrait orientation (after playing in forced landscape), the underlying view doesn't rotate back. I have to manually rotate the device to landscape and back to portrait to trigger updating of the orientation. Is there some way I can trigger this kind of update programatically?

The following set of screenshots should illustrate what I mean:

enter image description here enter image description here enter image description here

NB: For various reasons, using MPMoviePlayerViewController is not possible.

Alcove answered 20/2, 2014 at 14:45 Comment(4)
I submitted a bug to Apple on this issue months ago. I suggest you do the same. The problem is that the orientation methods of the underlying view controller are not being consulted.Geomorphic
Any suggestions for a work-around?Alcove
No. You could try to prevent use of fullscreen mode. Or just don't use MPMoviePlayerController. Basically this is just a big incoherency from Apple and developers need to keep at them until they fix it.Geomorphic
have you checked this answer yet. there is a sample project attached to it that might help you. #15947849Bisulfate
E
11

Hi all I had same problem I resolved it -

Here is my complete code....

You need to first change in appdelegate:

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if ([[[NowPlaying sharedManager] playerViewController] allowRotation])//Place your condition here
{
    return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}

Register Notifications for the full screen control:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerWillEnterFullscreenNotification:)
                                             name:MPMoviePlayerWillEnterFullscreenNotification
                                           object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerWillExitFullscreenNotification:)
                                             name:MPMoviePlayerWillExitFullscreenNotification
                                           object:nil];

Then add line of code in the player controller:

- (void)moviePlayerWillEnterFullscreenNotification:(NSNotification *)notification
{
dispatch_async(dispatch_get_main_queue(), ^
               {
                   self.allowRotation = YES;
               });
}



- (void)moviePlayerWillExitFullscreenNotification:(NSNotification *)notification
{
self.allowRotation = NO;
[self.moviePlayerController setControlStyle:MPMovieControlStyleNone];

dispatch_async(dispatch_get_main_queue(), ^
               {

                   //Managing GUI in pause condition
                       if (self.currentContent.contentType == TypeVideo && self.moviePlayerController.playbackState == MPMoviePlaybackStatePaused)
                   {
                       [self.moviePlayerController pause];
                       if (self.playButton.selected)
                           self.playButton.selected = NO;
                   }
                   self.view.transform = CGAffineTransformMakeRotation(0);
                   [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
                   self.view.bounds = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
               });
}

This code is tested in iOS6 and iOS7 working fine. Thanks :)

Please let me know if there is any question.....

Etter answered 8/4, 2014 at 8:23 Comment(4)
what condition i have to check here?if ([[[NowPlaying sharedManager] playerViewController] allowRotation])//Place your condition here and what is mean by now playing?Hydrastinine
Hi Vijay, thanks for the code. it is working fine after removing the dispatch_async code in the WillExitFullScreen method. Can you brief me why you put the code which is not useful and what is TypeVideo??Detailed
Thanks Satya for comment. I used dispatch_async for accessing main thread because in my case when I am entering into landscape mode my previous GUI is getting distorted while animating. In my case I am playing audio and video on same player and whenever a video start playing it gets full screen not in audio song. So I used TypeVideo for video songs.Etter
Sorry karthikeyan for late reply. [[[NowPlaying sharedManager] playerViewController] allowRotation] In my case PlayerViewController get Landscape in case I am entering in full screen player mode. So at the time of -> '- (void)moviePlayerWillEnterFullscreenNotification' notification method calling on playerview controller, I am saying that yes allow all rotation now by 'self.allowRotation = YES;' Please let me know if you are not clear on this. Thanks.Etter
L
5

You need to subclass and provide landscape as supported interface orientation.

@interface MyMovieViewController : MPMoviePlayerViewController
@end

@implementation MyMovieViewController

- (BOOL)shouldAutorotate 
{
    return YES;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations 
{
    return UIInterfaceOrientationMaskLandscape;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}

@end
Lylelyles answered 3/3, 2014 at 18:27 Comment(0)
W
2

You could try to "force" an orientation refresh to let the system handle the correct orientation for you:

- (void)forceOrientationRefresh
{
    // Force orientation refresh
    [self presentModalViewController:[UIViewController new]
                            animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}

It's hack-ish but it works.

Wan answered 28/2, 2014 at 1:53 Comment(0)
A
1

You can change your orientation programmatically like this

-(void)viewDidAppear:(BOOL)animated
{

     if(UIDeviceOrientationIsPortrait(self.interfaceOrientation)){
        if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
        {
            objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationLandscapeLeft );

        }
    }

}

And don´t forget to add #import <objc/message.h>

Amain answered 3/3, 2014 at 16:53 Comment(0)
D
0

This might sound crazy but, can you try saving locally the last orientation before opening the video view controller and then using application:supportedInterfaceOrientationsForWindow: to return the saved orientation and force the view controller to stay on it and not rotate.

Disinclination answered 26/2, 2014 at 17:31 Comment(0)
M
0

I think you can register your viewcontroller for device orientation and call viewcontroller's orientation method forcefully.

Magi answered 4/3, 2014 at 6:30 Comment(0)
O
0

You use supportedIterfaceOrientationsForWindow then look for: MPInlineVideoFullscreenViewController. It is a bit tricky to find right view controller but it works.

Here is the sample code:

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
    if ([NSStringFromClass([self.window.rootViewController.presentedViewController.presentedViewController class]) isEqualToString:@"MPInlineVideoFullscreenViewController"]){
    return UIInterfaceOrientationMaskAllButUpsideDown;
}
    return UIInterfaceOrientationMaskLandscape;
}
Oil answered 22/5, 2015 at 14:32 Comment(0)
C
-1

you need to add this code for iOS7 it works perfect and simple

-(NSUInteger)supportedInterfaceOrientations {

    return UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

.... creating a player
MPMoviePlayerViewController *mp =[[MPMoviePlayerViewController alloc] initWithContentURL:url];
...make settings and present it
[self presentMoviePlayerViewControllerAnimated:mp];
Colloquium answered 21/4, 2014 at 9:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.