MPMoviewPlayerController全屏播放旋转,底层UIViewController仅限纵向模式(不允许旋转)

时间:2011-02-16 08:32:33

标签: iphone cocoa-touch uitabbarcontroller rotation mpmovieplayercontroller

喂,

我有一个简单的应用程序,它包含带有两个UIViewControllers的UITabBarController。两个UIViewControllers都只是纵向(不允许旋转)。一个UIViewController的UIView确实包含MPMoviePlayerController的视图,允许在该视图中播放视频,并可通过控件(MPMovieControlStyleEmbedded)使其全屏显示。代码很简单,看起来像......

__moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:@"MOVIE_URL"]];
__moviePlayer.controlStyle = MPMovieControlStyleEmbedded;
__moviePlayer.view.frame = CGRectMake( 10, 10, 300, 200 );
__moviePlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
__moviePlayer.shouldAutoplay = NO;
[__moviePlayer prepareToPlay];  
[self.view addSubview:__moviePlayer.view];

...这确实很有效,除非用户切换到全屏播放,我希望允许旋转以允许横向播放。旋转不起作用,因为UITabBarController不允许它(以及两个UIViewControllers)。

所以,我尝试了两种方法,但它们都没有按预期工作。

1)Subclassed UITabBarController

我添加了属性BOOL __allowRotation,如果设置为YES,我会在UITabBarController的shouldAutorotateToInterfaceOrientation方法中返回YES。

我正在侦听MPMoviePlayerDidEnterFullscreenNotification和MPMoviePlayerWillExitFullscreenNotification通知,将此属性设置为YES和NO。

它确实有效,但问题是,当用户以横向结束视频播放时,基础视图不会旋转回纵向。旋转回纵向的唯一方法是使用私有API,这不是没有。

2)视图/图层转换

我也尝试过侦听MPMoviePlayerDidEnterFullscreenNotification和MPMoviePlayerWillExitFullscreenNotification通知。

当我收到MPMoviePlayerDidEnterFullscreenNotification时,我正在启动UIDevice方向通知以获取设备方向。我正在尝试根据当前的设备方向转换MPMoviePlayerController的视图层,但它有点免疫,因为它什么都不做。我可以为转换属性分配任何内容,但它什么都不做。

没有什么不完全正确。当我在旋转期间应用变换时,当我从全屏切换回嵌入式视频播放时,我可以看到此变换的效果。

3)分开UIWindow

我还没有对此进行测试,但我发现某个地方MPMoviePlayerController为全屏播放创建单独的UIWindow,应该可以通过[[UIApplication sharedApplication] windows]访问。这解释了为什么在全屏播放期间不应用转换。

但是我非常不喜欢这个解决方案,因为UIWindow无法识别,我不想使用像objectAtIndex:1这样的魔术常量,或者将转换应用到除主要部分之外的所有UIWindows等。

除了可以修改底层实现并且它将停止工作的事实。

问题

所以,问题是,当底层UIView(即UIView的UIViewController)禁止旋转并仅允许纵向时,如何允许MPMoviePlayerController全屏播放仅旋转?

5 个答案:

答案 0 :(得分:8)

我的情况非常相似。我的应用程序仅限肖像。但我需要以任何方向显示全屏视频,然后在用户退出全屏模式后返回纵向方向。

Split方法对我不起作用,因为我想让用户全屏观看并嵌入视频,并在模式之间切换,不会失去播放位置,也不会有任何暂停。< / p>

我发现了这个解决方法:

首先,我有一个根UINavigationController子类,它接收有关旋转的所有消息。

我禁止在此控制器中旋转:

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

我凌驾于

- (id) initWithRootViewController:(UIViewController *)rootViewController; method. 

添加对设备方向修改的支持:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(receivedRotate:) name: UIDeviceOrientationDidChangeNotification object: nil];

现在我有一个处理程序receivedRotate: - 尽管没有自动旋转到除肖像之外的任何方向,它捕获所有设备旋转:

- (void) receivedRotate:(NSNotification*) notify {
    if(isVideoFullscreen) {
        UIDeviceOrientation toInterfaceOrientation = [[UIDevice currentDevice] orientation];
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.4];
        [UIView setAnimationCurve:2];

        if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft){
            self.view.transform = CGAffineTransformMakeRotation(-M_PI_2);
            [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
            self.view.bounds = CGRectMake(0, 0, 1024, 768);
        } else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
            self.view.transform = CGAffineTransformMakeRotation(M_PI_2);
            [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight]; 
            self.view.bounds = CGRectMake(0, 0, 1024, 768);            
        } else if(toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
            self.view.transform = CGAffineTransformMakeRotation(M_PI);
            [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortraitUpsideDown];
            self.view.bounds = CGRectMake(0, 0, 768, 1024);
        } else if(toInterfaceOrientation == UIInterfaceOrientationPortrait) {
            self.view.transform = CGAffineTransformMakeRotation(0);
            [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
            self.view.bounds = CGRectMake(0, 0, 768, 1024);
        }

        [UIView commitAnimations];
    }

}

我只是检查设备的旋转,并相应地旋转我的视图。

然后 - 当视频全屏时,根控制器如何知道? 只需将另外两个消息处理程序添加到init:

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

处理程序本身:

- (void) willEnterFullscreen: (NSNotification *) notify {
    isVideoFullscreen = YES;
}

- (void) willExitFullscreen: (NSNotification *) notify {
    self.view.transform = CGAffineTransformMakeRotation(0);
    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
    self.view.bounds = CGRectMake(0, 0, 768, 1024);    
    isVideoFullscreen = NO;
}

退出全屏时 - 我们恢复纵向方向。 所以,这对我有用,希望它会帮助别人。

答案 1 :(得分:6)

您可以尝试以模态方式呈现新的UIViewController(使用shouldAutorotate YES),并在发送MPMoviePlayerWillEnterFullscreenNotification时将__moviePlayer.view添加到此控制器中。当moviePlayer退出全屏时,反之亦然。

答案 2 :(得分:1)

在app delegate中注册MPMoviePlayerWillExitFullscreenNotification和MPMoviePlayerWillEnterFullscreenNotification并使用实例变量处理方向。


-(void)moviePlayerFullScreen:(NSNotification *)notification
{
    if ([notification.name isEqualToString:@"MPMoviePlayerWillEnterFullscreenNotification"]) {

        self.supportedOrientation=UIInterfaceOrientationMaskAll;

    }
    else if ([notification.name isEqualToString:@"MPMoviePlayerWillExitFullscreenNotification"])
    {
        self.supportedOrientation=UIInterfaceOrientationMaskPortrait;

    }
 }
 - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window  {
    return self.supportedOrientation;
}

答案 3 :(得分:0)

MPMoviePlayerViewController有自己的功能来模拟显示视频:

NSURL *videoURL = [NSURL fileURLWithPath:video.path];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];

//Calls for movie playback once video is finished
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(moviePlayBackDidFinish:)
                                             name:MPMoviePlayerPlaybackDidFinishNotification
                                           object:moviePlayer];
playerView = [[MPMoviePlayerViewController alloc]init];
[moviePlayer setControlStyle:MPMovieControlStyleFullscreen];
[playerView setView:moviePlayer.view];

[moviePlayer.view setFrame: self.view.bounds];  
[self presentMoviePlayerViewControllerAnimated:playerView];

[moviePlayer play];
NSLog(@"playing video view");

答案 4 :(得分:0)

大家好我遇到同样的问题我解决了 -

这是我的完整代码......

您需要先在appdelegate中进行更改:

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

注册全屏控制通知:

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

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

然后在播放器控制器中添加代码行:

- (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);
               });
}

此代码在iOS6和iOS7中经过测试正常运行。感谢

如果有任何问题,请告诉我.....