1. 程式人生 > >禁止自動橫屏下的視訊播放強制旋轉

禁止自動橫屏下的視訊播放強制旋轉

問題的由來

這個標題有點繞,所以我來解釋一下。

之前專案開發的時候需要用到一個視訊播放的第三方庫,但是這個第三方庫在從小螢幕播放切換到大螢幕播放的時候,是需要開啟專案的自動旋轉支援的。也就是

圖一

第三方視訊播放庫 BMPlayer 這個庫中有許多細節的部分無法滿足實際使用,因此我下了原始碼後自己根據需求修改。

然而實際應用中,許多的 App 的要求是需要禁止橫屏的。因為大多數 App(竊以為除了遊戲以外的)即使寫好了約束,也都不會針對橫屏下的 UI 作對應的優化。 因此我們需要自己針對工程禁用橫屏情況下,播放視訊時切換到全屏做自己的優化

問題的擴充套件

之前搜尋播放框架的時候沒有找到適當的,因此最後決定自己把 BMPlayer

的原始碼 down下來自己修改。雖然最後解決了(這也是本篇文章下面主要闡述的內容),但是解決方案是在AppDelegate中增加一個變數來控制當前App 的方向。實際上還是增加了庫和工程之間的耦合度。暫時還未找到更好的解決方案。

實現的效果

效果圖.gif

程式碼和說明(Swift 為例)

下面的原始碼中略去了不必要的程式碼

AppDelegate.swift 中

let appDelegate = UIApplication.shared.delegate as! AppDelegate
class AppDelegate: UIResponder, UIApplicationDelegate
, WXApiDelegate
{ var deviceOrientation = UIInterfaceOrientationMask.portrait // 去實現這個回撥代理 func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { return deviceOrientation } } 複製程式碼

在視訊播放庫中控制它的方向

點選全屏播放和恢復小螢幕時候兩個按鈕的對應方法

private func forceToPlayOnFullScreen() {
    let currentOrientation = UIDevice.current.orientation
    print("向右旋轉前 當前的方向 = ", currentOrientation.rawValue)
    
    appDelegate.deviceOrientation = .landscapeRight
    // 如果防止使用者在進入當前頁面時手機橫置,那麼當前的 device orientation 是 landscapeRight
    // 這時候,我們再去設定 landscapeRight,是不會引起廣播 "UIDeviceOrientationDidChangeNotification",因此手動呼叫一次
    let portraitValue = UIInterfaceOrientation.portrait.rawValue
    UIDevice.current.setValue(portraitValue, forKey: "orientation")
    
    let rightValue = UIInterfaceOrientation.landscapeRight.rawValue
    UIDevice.current.setValue(rightValue, forKey: "orientation")
    
}

private func forceToPlayOnOriginScreen() {
    let currentOrientation = UIDevice.current.orientation
    print("恢復垂直前當前的方向 = ", currentOrientation.rawValue)
    
    // 這裡為什麼要寫兩遍,在下面說明
    appDelegate.deviceOrientation = .portrait
    let rightValue = UIInterfaceOrientation.landscapeRight.rawValue
    UIDevice.current.setValue(rightValue, forKey: "orientation")
    
    let portraitValue = UIInterfaceOrientation.portrait.rawValue
    UIDevice.current.setValue(portraitValue, forKey: "orientation")
    
}

複製程式碼

關於程式碼設定了兩次方向的說明

一定很奇怪,為什麼兩次程式碼的呼叫中,設定方向的程式碼要寫兩遍呢

UIDevice.current.setValue

這是因為,視訊播放庫,這裡需要去獲取一個系統的廣播 UIDeviceOrientationDidChangeNotification.

說明

假設我們當前的螢幕是橫屏的情況

以 Bilibili 的播放頁面為例

此時系統會利用陀螺儀,雖然我們視覺上看上去,他並沒有向右旋轉,但是當前的方向UIDevice.current.orientation會變成landScapeRight.

因此我們如果這時候去呼叫

let rightValue = UIInterfaceOrientation.landscapeRight.rawValue
UIDevice.current.setValue(rightValue, forKey: "orientation")
複製程式碼

這個函式的時候,不會觸發廣播,因為系統會認為,其實我的方向沒有變化啊!

這也就是為什麼上面我們會先讓他的方向設為預設的 portrait再切回landscapeRight. 我曾經誤以為介面會不會旋轉回去一次再賺回來,但是實際測試發現倒是沒有出現類似的情景。