Just a Computer Graphics Studio & My Life

若在專案直接設定裝置面向(Device Orientation)為全部都勾選的話,就可以不用看這篇文章啦~就是因為我這專案除了播放影片之外,其它大多數的view都要固定為縱向(Portrait),所以我必須在特定播放影片的view中設定面向,使之能夠旋轉四個面向,如此來得省事!

Device Orientation

之前我有介紹過,可在特定view自動旋轉,是可以拿來用沒錯,然而這次的目標有點棘手,因為它是要在WebView中播放Youtube影片旋轉!為什麼說有點難搞呢?因為我ViewController中收不到裝置面向的訊號⋯⋯ 簡言之這篇文章的目的:希望在限制直向的App中,支援橫向播放embedded youtube影片。 要播放Youtube影片的程式碼可以參考我的文章:播放Youtube影片

/**
 Theme: Play Youtube Video in WebView to Rotate
 IDE: Xcode 5
 Language: Objective C
 Date: 103/03/21
 Author: HappyMan
 Blog: https://cg2010studio.wordpress.com/
 */
//在我的HMAppDelegate.h加入
@property (nonatomic) BOOL fullScreenVideoIsPlaying;
//在我的HMAppDelegate.m加入
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    if (self.fullScreenVideoIsPlaying) {
        return UIInterfaceOrientationMaskAll;
    }
    else {
        return UIInterfaceOrientationMaskPortrait;
    }
}
//在我的HMViewController.m實作
-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(youTubeStarted:) name:@"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(youTubeFinished:) name:@"UIMoviePlayerControllerWillExitFullscreenNotification" object:nil];
}
/*
-(void)viewDidDisappear:(BOOL)animated
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIMoviePlayerControllerWillExitFullscreenNotification" object:nil];
}
*/
-(void)youTubeStarted:(NSNotification *)notification
{
    HMAppDelegate *appDelegate = (HMAppDelegate*)[[UIApplication sharedApplication] delegate];
    appDelegate.fullScreenVideoIsPlaying = YES;
}
-(void)youTubeFinished:(NSNotification *)notification
{
    HMAppDelegate *appDelegate = (HMAppDelegate*)[[UIApplication sharedApplication] delegate];
    appDelegate.fullScreenVideoIsPlaying = NO;
}

註解掉那方法是因為順序不對,跳進全螢幕時就會執行viewDidDisappear,解除先前所註冊的觀察,直到跳出全螢幕時會執行viewWillAppear,這時候又會再註冊觀察,因而沒有執行到youTubeStarted和youTubeFinished,如此就讓layout爛掉。其實改在viewDidLoad註冊更好! 這程式碼對iPhone有效而對iPad無效,猜測是系統會再去判斷device,認為iPad的顯示範圍夠大,在web view點擊Youtube影片,就不會全螢幕播放。 原來web view中封閉實作的影片播放控制器不同於MPMoviePlayerController,在web view中其實是MPAVControllerUIMoviePlayerController,後者讓播放的樣子像MPMoviePlayerController。 所以Notification可以使用這些參數:

  • UIMoviePlayerControllerDidEnterFullscreenNotification
  • UIMoviePlayerControllerDidExitFullscreenNotification
  • UIMoviePlayerControllerWillExitFullscreenNotification
  • MPAVControllerPlaybackStateChangedNotification
  • AVPlayerItemDidPlayToEndTimeNotification

在視圖控制器中註冊觀察通知就可以根據需要來旋轉螢幕。然而由於這個不是公開的,所以不能保證能通過App Store審核,也不保證在將來的iOS版本中不會變化。 因為iPad在非全螢幕播放完Youtube影片,不會通知UIMoviePlayerControllerWillExitFullscreenNotification,此時我們可以使用AVPlayerItemDidPlayToEndTimeNotification取代之。 疑惑1:UIInterfaceOrientationMaskAll和UIInterfaceOrientationMaskAllButUpsideDown在iPhone實機上測試效果一樣是後者的效果。 註:參數定義

  • UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
  • UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),

更新

在iOS 8時,無法無法觀察事件:

  • UIMoviePlayerControllerDidEnterFullscreenNotification
  • UIMoviePlayerControllerDidExitFullscreenNotification
  • UIMoviePlayerControllerWillExitFullscreenNotification

只好找其他方法,現在只要在AppDelegate.m中加入判斷是哪個view controller,就能控制其轉向。iOS 8以前的作業系統相容。

- (NSUInteger)application:(UIApplication *)applicationsupportedInterfaceOrientationsForWindow:(UIWindow *)window {
  if ([[window.rootViewController presentedViewController]
     isKindOfClass:[MPMoviePlayerViewController class]] || [[window.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"MPInlineVideoFullscreenViewController")] || [[window.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"AVFullScreenViewController")]) {

      return UIInterfaceOrientationMaskAllButUpsideDown;
  }else {

      if ([[window.rootViewController presentedViewController]
         isKindOfClass:[UINavigationController class]]) {

          // look for it inside UINavigationController
          UINavigationController *nc = (UINavigationController *)[window.rootViewController presentedViewController];

          // is at the top?
          if ([nc.topViewController isKindOfClass:[MPMoviePlayerViewController class]]) {
              return UIInterfaceOrientationMaskAllButUpsideDown;

          // or it's presented from the top?
          } else if ([[nc.topViewController presentedViewController]
                    isKindOfClass:[MPMoviePlayerViewController class]]) {
              return UIInterfaceOrientationMaskAllButUpsideDown;
          }
      }
  }
  return UIInterfaceOrientationMaskPortrait;
}

題外話,其實那些事件名稱「字串」沒有被官方定為「常數」,就要特別注意未來相當有可能會變動。

參考:

Advertisements

Comments on: "[iOS] 在WebView播放Youtube影片旋轉" (2)

  1. […] 原先以為只要使用這個技巧:在WebView播放Youtube影片旋轉,就能完美地呈現全影幕影像縮放、移動、旋轉。但是呢⋯⋯按下「關閉」,回到上一個view,它沒有轉向回去⋯⋯ […]

    喜歡

  2. […] 同樣也可能遇到想要橫向和直向都能播放,先前也提到在WebView播放Youtube影片旋轉,我們也可註冊觀察來做到。 […]

    喜歡

發表留言

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

標籤雲

%d 位部落客按了讚: