疑难杂症攻克–自定义JS视频播放器控制栏全屏问题解决
前言
在做一个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"],
//....
}
//....
]
最后附上半屏和全屏的效果图: