前言
在做一個HarmonyOS應用項目的時候,需要自定義播放器(這裡選用的js元件),發現沒法在自定義播放器控制欄上做全屏播放的功能,翻遍官網和百度都沒法找到答案,并且發現之前有部落客寫到了自定義播放器時,這個全屏問題作為遺留問題一直沒解決,那麼我隻好想辦法攻克了,足足花了五六個小時才搞定。
核心疑難雜症
在自定義視訊播放器控制欄的時候,播放、暫停、進度條、時長顯示、倍速等功能都好實作,但是在全屏的時候,我們發現問題就來了。在做這些自定義功能的時候,我們肯定要優先看官方文檔提供的API支援,下表是官方的API支援。
從中可以看出隻需要調用requestFullScreen這個api即可請求全屏播放,但是調用之後會發現自己定義的控制欄就沒有辦法顯示出來了。
解決思路:
曾經想過的解決方案:
(1)修改requestFullScreen方法的底層源碼,重新編譯一個sdk出來。
HarmonyOS上這塊沒有開源,不用想了。
(2)自定義的控制欄沒有顯示出來會不會是因為全屏播放的時候控制欄和視訊的圖層層級關系導緻控制欄被遮擋了?結果通過各種設定z-index,發現也無法解決,放棄了,更換其它思路。
前面兩種一直都是陷入到了依賴官方提供的requestFullScreen方法去進行全屏,思維被限制住了,繼續圍繞這個發現怎麼也弄不出來。于是需要切換下思路,如果不用官方的這個api該如何實作全屏呢?
抛棄自帶api之後,我想到的實作播放器全屏并且能顯示自定義控制欄和隐藏自定義控制欄需要下面幾步:
(1)video元件和自定義控制欄所在的div元件包裹在stack元件進行布局。
(2)在data中設定stack元件寬度和高度需要的變量,半屏或全屏的時候會修改該值。
(3)全屏的時候需要先切換螢幕為橫屏方向,然後講stack元件的寬度和高度都設定為100%,同時還需要隐藏頁面中其它所有的元件。切換半屏的時候需要将螢幕切回豎屏,然後将寬度和高度都設定為全屏之前的值,并且顯示頁面中的所有其他元件。這裡還可以在做下延伸,針對視訊源的寬高比進行判斷,如果寬度大于高度則切成橫屏狀态的全屏模式,如果寬度小于高度,則是采用豎屏下的全屏模式。
(4)切換全屏還需要将系統自帶的狀态欄設定為隐藏,切換成半屏的時候在将狀态欄顯示出來。
後面我就沿着這個思路去想辦法解決了,第(1)和第(2)步很簡單,不過多介紹。第(3)步中要求一個核心技術點就是需要找到切換橫豎屏的api,然後去檢視官方api文檔發現js沒有切換橫豎屏的api,那麼咋辦呢?難道又要放棄嗎。No,這個時候可以想想java是否具備橫豎屏切換的api,結果發現java中是具備的,如下
//切換橫屏
abilityContext.setDisplayOrientation(AbilityInfo.DisplayOrientation.LANDSCAPE);
//切換豎屏
abilityContext.setDisplayOrientation(AbilityInfo.DisplayOrientation.PORTRAIT);
說到這裡,大家就應該知道如何做了吧,利用js和java混合開發即可,關于混合開發的細節我就不在本文中詳細講解了。
第(4)步中,顯示和隐藏系統狀态欄目前js直接有api可以實作,如下:
windowClass.setFullScreen(!this.isFullScreen, (err, data) => {
if (err) {
console.error('Failed to enable the full-screen mode. Cause: ' + JSON.stringify(err));
return;
}
console.info('Succeeded in enabling the full-screen mode. Data: ' + JSON.stringify(data));
});
同時,我們應該需要關閉app自帶的标題欄,這個隻需要在config.json中加入如下配置即可。
"module": {
//...
"metaData" : {
"customizeData" : [
{
"name": "hwc-theme",
"value": "androidhwext:style/Theme.Emui.NoTitleBar"
}
]
},
//...
}
這裡還有個重點需要強調,就是我們會在data中設定各種變量用來記錄播放狀态、進度、全屏狀态等,而在橫豎屏進行切換時,預設是會導緻FA的生命周期重繪的,那麼就會導緻data中的所有變量會被重新初始化,于是為了防止生命周期重繪,請務必在config.json中給需要的FA添加如下配置:
"abilities": [
{
"configChanges": ["orientation"],
//....
}
//....
]
最後附上半屏和全屏的效果圖: