【问题标题】:MPMoviewPlayerController fullscreen playback rotation with underlying UIViewController with portrait mode only (rotation disallowed)MPMoviewPlayerController 全屏播放旋转,底层 UIViewController 仅具有纵向模式(不允许旋转)
【发布时间】:2011-06-28 04:51:45
【问题描述】:

你好,

我有一个简单的应用程序,其中包含带有两个 UIViewController 的 UITabBarController。两个 UIViewController 都是纵向的(不允许旋转)。一个 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) 子类 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 之外的所有 UIWindows 应用转换等。

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

问题

那么,问题来了,当底层UIView(即UIView的UIViewController)禁止旋转只允许纵向时,如何让MPMoviePlayerController全屏播放只旋转?

【问题讨论】:

    标签: iphone cocoa-touch uitabbarcontroller rotation mpmovieplayercontroller


    【解决方案1】:

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

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

    你需要先改变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 中进行了测试,工作正常。谢谢

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

    【讨论】:

    • 如果([[[NowPlaying sharedManager] playerViewController] allowRotation])我需要在这里检查什么条件?我无法理解这个?你能给我关于这个的演示项目吗?
    【解决方案2】:

    在应用委托中注册 MPMoviePlayerWillExitFullscreenNotification 和 MPMoviePlayerWillEnterFullscreenNotification 并使用实例变量处理方向。

    -(void)moviePlayerFullScreen:(NSNotification *)通知 { if ([notification.name isEqualToString:@"MPMoviePlayerWillEnterFullscreenNotification"]) { self.supportedOrientation=UIInterfaceOrientationMaskAll; } else if ([notification.name isEqualToString:@"MPMoviePlayerWillExitFullscreenNotification"]) { self.supportedOrientation=UIInterfaceOrientationMaskPortrait; } } - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { 返回 self.supportedOrientation; }

    【讨论】:

    • 如何同时注册 MPMoviePlayerWillExitFullscreenNotification?iOS7 是否可以使用此代码?
    【解决方案3】:

    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】:

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

      Split 的方法对我不起作用,因为我想让用户全屏和嵌入观看视频,并在模式之间切换,不丢失播放位置,并且没有任何暂停。

      我找到了这个解决方法:

      首先,我有一个根 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;
      }
      

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

        • 你是对的。我盯着代码看了这么久,这并没有出现在我的脑海中。谢谢!它现在确实按预期工作。附:但我仍然认为它应该自动工作,因为全屏演示是由 MPMoviePlayerController 控制的。打算填补雷达错误...
        • 填充为 MPMoviePlayerController 错误 ID# 9009914 的增强功能,以允许全屏播放的自动旋转控制。
        • 我喜欢你的方法,但是当你在 modalVC 中展示它时,视频不会重新开始吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-02
        • 1970-01-01
        • 2012-01-15
        相关资源
        最近更新 更多