iOS播放器全屏方案

所有的視頻類App都會面臨一個播放器橫豎屏切換的問題,之前一直使用KVO強(qiáng)制修改設(shè)備方向達(dá)到豎屏轉(zhuǎn)為橫屏。

UIDevice.current.setValue(value, forKey: "orientation")

目前看來,優(yōu)酷視頻貌似依然使用的這個方法,具體表現(xiàn)為statusBar會跟著屏幕做旋轉(zhuǎn)動畫,而且播放器下的其他控件會轉(zhuǎn)到橫屏布局。
但是這個方法是非官方提供的API,隨著系統(tǒng)版本的更迭有可能會失效。
所以許多公司采用了modal出一個只支持橫屏的控制器來達(dá)到橫豎屏切換的目的。

思路

有以下兩種方法實現(xiàn)。

方法1

豎屏轉(zhuǎn)橫屏?xí)r:由豎屏控制器做一個播放器由小變大,并且旋轉(zhuǎn)為橫屏的動畫,動畫結(jié)束時做一個無動畫的present
橫屏轉(zhuǎn)豎屏?xí)r:做一個無動畫的dimiss,dimiss完成后,依然由豎屏控制器做播放器由大變小并且旋轉(zhuǎn)回原處的動畫。
目前看來,愛奇藝和bilibili貌似使用這個方式,具體表現(xiàn)為豎屏切橫屏?xí)r,播放器動畫完成后,statusBar無動畫轉(zhuǎn)為橫屏;橫屏切豎屏?xí)r,statusBar先無動畫轉(zhuǎn)為豎屏,然后才開始播放器動畫。

這種方法的坑

問題

但是目前這個方法有一個問題,就是在橫屏轉(zhuǎn)豎屏?xí)r,畫面偶爾會閃一下。

問題分析

畫面偶爾會閃一下,是在默認(rèn)的模式下,控制器的.modalPresentationStyle = UIModalPresentationStyle.fullScreen,此時,當(dāng)控制器A present 出控制器B,完成present動作后,控制器B的view會添加進(jìn)一個UITransitionView類型的View中(即我們在自定義轉(zhuǎn)場動畫時的transitionContext.containerView),UITransitionView是直接添加在Window上的,而控制器A的view會暫時從視圖層級中移除。當(dāng)無動畫dimiss時,UITransitionView先從Window移除,然后控制器A的View在添加到window上,在這中間有可能會造成閃動。
所以只要保證完成present動作后,控制器A的view依然保持在視圖層級中即可。

解決方案

解決方案1

在UIModalPresentationStyle中有一個枚舉類型:.overFullScreen,這個方式的作用就是保證完成present動作后,控制器A的view依然保持在視圖層級中。
所以我們設(shè)置控制器B的.modalPresentationStyle = .overFullScreen,測試證明這個屬性可以保證完成present動作后,控制器A的view依然保持在視圖層級中,但是重力感應(yīng)的方向不會發(fā)生改變。所以這個方案不可用。

解決方案2

既然系統(tǒng)沒有可以使用的,那我們可以在presen完成后,自己手動把控制器A 的View插入到控制器BView的下邊。有兩種方式,
方式一:
將控制器A的view直接插入到UITransitionView內(nèi)的控制器B的View下

// 方式一:將當(dāng)前控制器的view插入到 橫屏view的下方
controller.view.superview?.insertSubview(strongSelf.view, belowSubview: controller.view)

方式二:
將window的rootViewController的View插入到Window之上,UITransitionView之下,這種方式的效果和.overFullScreen的效果一樣。
這兩種方式都可以,可以根據(jù)實際情況來選擇使用

// 方式二:.overFullScreen的實際效果
if let keyWindow = UIApplication.shared.keyWindow,let rootViewController = UIApplication.shared.keyWindow?.rootViewController, let containerView = controller.view.superview  {
    keyWindow.insertSubview(rootViewController.view, belowSubview: containerView)
 }

方法2

自定義轉(zhuǎn)場動畫!
目前看來,騰訊視頻有可能使用這個方式。
但是這個方式也有一個問題,就是自動轉(zhuǎn)場動畫后,從橫屏返回豎屏,本該豎屏的控制器不能變回豎屏,這應(yīng)該是蘋果的一個bug,目前我的解決方式是在將要展現(xiàn)的生命周期方法中強(qiáng)行設(shè)置為正確的fram

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    print("Tabbar - WillAppear",view.frame)
    // 因為 presented 完成后,控制器的view的frame會錯亂,需要每次將要展現(xiàn)的時候強(qiáng)制設(shè)置一下
    view.frame = UIScreen.main.bounds
}

demo

GitHub地址:iOSPlayerVerticalAndHorizontalScreenDemo

效果圖

Demonstration.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容