若在專案直接設定裝置面向(Device Orientation)為全部都勾選的話,就可以不用看這篇文章啦~就是因為我這專案除了播放影片之外,其它大多數的view都要固定為縱向(Portrait),所以我必須在特定播放影片的view中設定面向,使之能夠旋轉四個面向,如此來得省事!
之前我有介紹過,可在特定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中其實是MPAVController和UIMoviePlayerController,後者讓播放的樣子像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; }
題外話,其實那些事件名稱「字串」沒有被官方定為「常數」,就要特別注意未來相當有可能會變動。
參考:
- [iOS] autorotation for youtube embedded video
- iOS 6.0+ autorotation for youtube embedded video
- How to receive NSNotifications from UIWebView embedded YouTube video playback
- UIWebView中視頻播放屏幕自動旋轉,app不支持旋轉但是某一個頁面需要旋轉等
- App Tour : Part 3 – Handling full screen video
- Detecting UIWebView finish to play youtube video on iPad
- Youtube video not playing in landscape mode in iOS 8
Comments on: "[iOS] 在WebView播放Youtube影片旋轉" (3)
[…] 先前寫了篇文章:在WebView播放Youtube影片旋轉,確實可以做到。不過iOS 9之後又有稍微變化,只好改寫它囉~ […]
讚讚
[…] 原先以為只要使用這個技巧:在WebView播放Youtube影片旋轉,就能完美地呈現全影幕影像縮放、移動、旋轉。但是呢⋯⋯按下「關閉」,回到上一個view,它沒有轉向回去⋯⋯ […]
讚讚
[…] 同樣也可能遇到想要橫向和直向都能播放,先前也提到在WebView播放Youtube影片旋轉,我們也可註冊觀察來做到。 […]
讚讚