MPMoviePlayerController fullscreen quirk in iPad

2019-01-31 14:00发布

问题:

I want to show a MPMoviePlayerController in a view controller and let the user toggle full screen with the default controls, like the YouTube app. I'm using the following code in a bare-bones example:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.player = [[MPMoviePlayerController alloc] init];
    self.player.contentURL = theURL;
    self.player.view.frame = self.viewForMovie.bounds;
    self.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self.viewForMovie addSubview:player.view];
    [self.player play];
}

This works well until the user makes the video full screen, rotates the device and taps on the screen. The status bar is shown in the wrong position, as shown in the screenshot below.

I'm working with the template Tab Bar Application for iPad. I've only added the viewDidLoad above, the view variables and an UIView in the XIB to show the movie player.

What am I doing wrong?

回答1:

Yeah, I'm experiencing this problem as well. It definitely appears to be a bug in the MPMoviePlayerController itself.

The workaround I've settled on in my application is to just correct the status bar myself when I exit fullscreen mode:

- (void)playerDidExitFullscreen:(NSNotification *)notification {
    MPMoviePlayerController *moviePlayer = (MPMoviePlayerController *) notification.object;

    if (moviePlayer == self.player) {
        UIApplication *app = [UIApplication sharedApplication];
        if (app.statusBarOrientation != self.interfaceOrientation) {
            [app setStatusBarOrientation:self.interfaceOrientation animated:NO];
        }
    }
}

This doesn't fix the problem while in fullscreen mode, but it does fix it afterwards.

Note of course that the function needs to be added to the notification:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerDidExitFullscreen:) name:MPMoviePlayerDidExitFullscreenNotification object:nil];


回答2:

Is shouldAutorotateToInterfaceOrientation:interfaceOrientation returning YES for all of the supported orientations?

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}

If you provided more of your code it would help.



回答3:

are you using interface builder for your UI? if so make sure you set the view's orientation to 'landscape' in the view attributes inspector.



回答4:

Had the same problem, just spent half a day sorting it out. With the iPad in portrait orientation, whenever I started a video using the sample code (or any I could find on the net) the video and control bar were formatted for portrait, and hence all over the place on the screen.

Anyway, the following works for me.

  /* Call the code like below:
        int iLandscape;
        if( newOrientation==UIInterfaceOrientationLandscapeLeft || newOrientation==UIInterfaceOrientationLandscapeRight )
             iLandscape=1;

        [self PlayVideo:iLandscape fullscreen:1]
    */
        //////////////////////////////////////////////////////////////////////////
        - (void)PlayVideo:(int)iLandscape fullscreen:(int)iFullScreen 
        {
            NSString *url = [[NSBundle mainBundle] pathForResource:@"myvideofile" ofType:@"m4v"];

        if( iFullScreen==0 )
        {
            MPMoviePlayerController *player2 = 
                [[MPMoviePlayerController alloc] 
                    initWithContentURL:[NSURL fileURLWithPath:url]];

            [[NSNotificationCenter defaultCenter] 
                addObserver:self
                   selector:@selector(movieFinishedCallback:)
                       name:MPMoviePlayerPlaybackDidFinishNotification
                     object:player2];

            //---play partial screen---
            player2.view.frame = CGRectMake(0, 0, m_iScreenWidth, m_iScreenHeight);
            [self addSubview:player2.view];
            //---play movie---
            [player2 play];
        }   
        else
        {
            MPMoviePlayerViewController *playerViewController = [[MPMoviePlayerViewController alloc] 
                initWithContentURL:[NSURL fileURLWithPath:url]];

            [[NSNotificationCenter defaultCenter] 
                addObserver:self
                   selector:@selector(movieFinishedCallback:)
                       name:MPMoviePlayerPlaybackDidFinishNotification
                     object:[playerViewController moviePlayer]];

            if( iLandscape )
            {
                playerViewController.view.frame = CGRectMake(0, 0, m_iScreenWidth, m_iScreenHeight);
            }
            [self addSubview:playerViewController.view];
            //play movie
            MPMoviePlayerController *player = [playerViewController moviePlayer];
            player.scalingMode=MPMovieScalingModeAspectFit;
            [player play];
        }
    }


    //////////////////////////////////////////////////////////////////////////
    - (void) movieFinishedCallback:(NSNotification*) aNotification 
    {
        MPMoviePlayerController *player = [aNotification object];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:player];    
        [player autorelease];    
        [player.view removeFromSuperview];
    }


回答5:

Did you solve this issue?

[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];

This code might help you.



回答6:

Found it.

Had the same problem - here is what I did. I would suggest adding the code to your project one by one to see exactly how it works.

First - I put things is portrait mode.

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];

Then I shoved the movie down onto the status bar. Note - this assumes that the video has a 4x3 aspect ratio

theVideo = [[MPMoviePlayerController alloc] initWithContentURL: [NSURL fileURLWithPath : path]];
float aspectRatio = (3.0f/4.0f);
float theMovieHeight = [self view].bounds.size.width * aspectRatio;
[[theVideo view] setFrame:(CGRectMake(0, [self view].bounds.size.height - theMovieHeight, [self view].bounds.size.width, theMovieHeight ))]; 

Then, in the place where the application starts up (in my project, it is in the didFinishLaunchingWithOptions function) - anyway, you just need access to the window object.

float aspectRatio = (3.0f/4.0f);
float theMovieHeight = self.window.bounds.size.width * aspectRatio;
float theSpaceAboveTheMovie = self.window.bounds.size.height - theMovieHeight;
float whereTheMovieShouldBeCentered = (self.window.bounds.size.height - theMovieHeight) / 2;

CGAffineTransform theTransform = CGAffineTransformMakeTranslation(0,0);

theTransform = CGAffineTransformScale(theTransform, 1.0f/aspectRatio, 1.0f/aspectRatio);
theTransform = CGAffineTransformTranslate(theTransform, -whereTheMovieShouldBeCentered, 0);
theTransform = CGAffineTransformRotate(theTransform, M_PI / 2);
theTransform = CGAffineTransformTranslate(theTransform, 0, -theSpaceAboveTheMovie);

[self.window setTransform:theTransform];

Remember that affine transforms are done in reverse order. So if you want to see what each transform is doing (I suggest you should), comment out the first three

Here you should see the movie and status bar centered on the page

//  theTransform = CGAffineTransformScale(theTransform, 1.0f/aspectRatio, 1.0f/aspectRatio);
//  theTransform = CGAffineTransformTranslate(theTransform, -whereTheMovieShouldBeCentered, 0);
//  theTransform = CGAffineTransformRotate(theTransform, M_PI / 2);
    theTransform = CGAffineTransformTranslate(theTransform, 0, -theSpaceAboveTheMovie);

Then the first two

Here you should see the movie and status bar rotated and no longer centered

//  theTransform = CGAffineTransformScale(theTransform, 1.0f/aspectRatio, 1.0f/aspectRatio);
//  theTransform = CGAffineTransformTranslate(theTransform, -whereTheMovieShouldBeCentered, 0);
    theTransform = CGAffineTransformRotate(theTransform, M_PI / 2);
    theTransform = CGAffineTransformTranslate(theTransform, 0, -theSpaceAboveTheMovie);

Here you should see it rotated and centered

//  theTransform = CGAffineTransformScale(theTransform, 1.0f/aspectRatio, 1.0f/aspectRatio);
    theTransform = CGAffineTransformTranslate(theTransform, -whereTheMovieShouldBeCentered, 0);
    theTransform = CGAffineTransformRotate(theTransform, M_PI / 2);
    theTransform = CGAffineTransformTranslate(theTransform, 0, -theSpaceAboveTheMovie);

And with them all, it is rotated and fullscreen

You can download my sample code here.



回答7:

Try this

 - (void)willEnterFullscreen:(NSNotification*)notification {
     NSLog(@"willEnterFullscreen");

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
  }

 - (void)enteredFullscreen:(NSNotification*)notification {
     NSLog(@"enteredFullscreen");
 }

- (void)willExitFullscreen:(NSNotification*)notification {
    NSLog(@"willExitFullscreen");

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];


}

- (void)exitedFullscreen:(NSNotification*)notification {
    NSLog(@"exitedFullscreen");

    [[NSNotificationCenter defaultCenter] removeObserver:self];
}