文章目录
- 背景
- 方法总览
- 场景一:视频全屏播放
- 场景二:查看窗口属性
- 场景三:状态栏颜色跟随页面主题
- 场景四:全面屏安全区域适配
- 场景五:特殊节日灰阶模式
- WindowUtil 方法调用时序图
- 写在最后
背景
近期发现一款很有意思的HarmonyOS 三方库, 地址 @pura/harmony-utils(V1.4.0) , 作者是"桃花镇童长老", 我这里也是直接通过该作者公布的源码进行案例编写进行,写了到目前写了一部分demo ,感觉确实很有帮助,这里呢也是开始写一个系列的演示demo 供大家参考。如有帮助可以在OpenHarmony中进行下载安装进行使用哦
案例demo导航展示
↓↓↓↓↓↓接下来言归正传 ↓↓↓↓
视频播放全屏、阅读页沉浸式、游戏全屏——这三种场景都是 HarmonyOS 开发里的高频需求,用 WindowUtil 来实现。
把 Demo 里涉及的方法串起来,组成一个完整的全屏开发方案。
方法总览
场景一:视频全屏播放
视频进入全屏时需要:隐藏系统栏 + 开启沉浸式布局 + 横屏 + 屏幕常亮
// 1. 精细隐藏系统栏(带动画)this.Btn('setSpecificSystemBarEnabled("status", false) 隐藏状态栏','#E74C3C',()=>{WindowUtil.setSpecificSystemBarEnabled('status',false,true).then(()=>{this.addLog('setSpecificSystemBarEnabled("status", false, animation=true)');}).catch((e:Error)=>{this.addLog(`Error:${e.message}`);});})this.Btn('setSpecificSystemBarEnabled("navigation", false)','#922B21',()=>{WindowUtil.setSpecificSystemBarEnabled('navigation',false).then(()=>{this.addLog('setSpecificSystemBarEnabled("navigation", false)');}).catch((e:Error)=>{this.addLog(`Error:${e.message}`);});})// 2. 开启沉浸式布局this.Btn('setWindowLayoutFullScreen(true) 沉浸式','#16A085',()=>{WindowUtil.setWindowLayoutFullScreen(true).then(()=>{this.addLog('setWindowLayoutFullScreen(true) → 开启沉浸式布局');}).catch((e:Error)=>{this.addLog(`Error:${e.message}`);});})// 3. 横屏Button('横屏').layoutWeight(1).height(36).fontSize(12).fontColor('#fff').backgroundColor('#2980B9').borderRadius(6).onClick(()=>{WindowUtil.setPreferredOrientation(window.Orientation.LANDSCAPE).then(()=>{this.addLog('setPreferredOrientation(LANDSCAPE)');}).catch((e:Error)=>{this.addLog(`Error:${e.message}`);});})// 4. 屏幕常亮this.Btn('setWindowKeepScreenOn(true) 屏幕常亮','#F39C12',()=>{WindowUtil.setWindowKeepScreenOn(true).then(()=>{this.addLog('setWindowKeepScreenOn(true) → 已开启常亮');}).catch((e:Error)=>{this.addLog(`Error:${e.message}`);});})退出全屏时,反向操作:显示系统栏、关闭沉浸式、竖屏、关闭常亮。
场景二:查看窗口属性
进入特殊页面前,先查询当前窗口状态:
this.Btn('getWindowProperties() 查询窗口属性','#4A90E2',()=>{try{constprops=WindowUtil.getWindowProperties();this.addLog(`type=${props.type}isFullScreen=${props.isFullScreen}isPrivacyMode=${props.isPrivacyMode}`);this.addLog(`brightness=${props.brightness}focusable=${props.focusable}touchable=${props.touchable}`);}catch(e){this.addLog(`Error:${e}`);}})this.Btn('isFullScreen()','#2980B9',()=>{try{this.addLog(`isFullScreen() →${WindowUtil.isFullScreen()}`);}catch(e){this.addLog(`Error:${e}`);}})this.Btn('isLayoutFullScreen()','#0E6655',()=>{try{this.addLog(`isLayoutFullScreen() →${WindowUtil.isLayoutFullScreen()}`);}catch(e){this.addLog(`Error:${e}`);}})场景三:状态栏颜色跟随页面主题
不同页面有不同的主题色,状态栏颜色需要配套:
// 品牌蓝色主题页this.Btn('setWindowSystemBarProperties 状态栏蓝色','#6C3483',()=>{WindowUtil.setWindowSystemBarProperties({statusBarColor:'#FF4A90E2',statusBarContentColor:'#FFFFFFFF',navigationBarColor:'#FF2C3E50',navigationBarContentColor:'#FFFFFFFF'}).then(()=>{this.addLog('setWindowSystemBarProperties → 成功(状态栏蓝色)');}).catch((e:Error)=>{this.addLog(`Error:${e.message}`);});})// 恢复默认色this.Btn('setWindowSystemBarProperties 恢复默认色','#5B2C6F',()=>{WindowUtil.setWindowSystemBarProperties({statusBarColor:'#0x66000000',statusBarContentColor:'#0xE5FFFFFF',}).then(()=>{this.addLog('setWindowSystemBarProperties → 恢复默认');}).catch((e:Error)=>{this.addLog(`Error:${e.message}`);});})场景四:全面屏安全区域适配
开启全屏布局后,内容可能被刘海、导航条遮挡,需要获取规避区高度:
// 获取系统规避区(包含状态栏高度和导航栏高度)this.Btn('getWindowAvoidArea(SYSTEM)','#2C3E50',()=>{try{constarea=WindowUtil.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);this.addLog(`getWindowAvoidArea(SYSTEM) topRect.height=${area.topRect.height}bottomRect.height=${area.bottomRect.height}`);}catch(e){this.addLog(`Error:${e}`);}})// 刘海屏规避区this.Btn('getWindowAvoidArea(CUTOUT) 刘海屏','#212F3C',()=>{try{constarea=WindowUtil.getWindowAvoidArea(window.AvoidAreaType.TYPE_CUTOUT);this.addLog(`getWindowAvoidArea(CUTOUT) topRect.height=${area.topRect.height}`);}catch(e){this.addLog(`Error:${e}`);}})// 导航指示条规避区this.Btn('getWindowAvoidArea(NAVIGATION_INDICATOR)','#1B2631',()=>{try{constarea=WindowUtil.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);this.addLog(`getWindowAvoidArea(NAVIGATION_INDICATOR) bottomRect.height=${area.bottomRect.height}`);}catch(e){this.addLog(`Error:${e}`);}})// 软键盘规避区(输入框页面用)this.Btn('getWindowAvoidArea(KEYBOARD) 软键盘','#17202A',()=>{try{constarea=WindowUtil.getWindowAvoidArea(window.AvoidAreaType.TYPE_KEYBOARD);this.addLog(`getWindowAvoidArea(KEYBOARD) bottomRect.height=${area.bottomRect.height}`);}catch(e){this.addLog(`Error:${e}`);}})场景五:特殊节日灰阶模式
结合亮度和灰阶控制,做特殊纪念日的灰色模式:
// 灰阶滑块@StategrayScaleValue:number=0;Slider({value:this.grayScaleValue*100,min:0,max:100,step:1}).width('100%').showTips(true).onChange(v=>{this.grayScaleValue=v/100;})this.Btn(`setWindowGrayScale(${this.grayScaleValue.toFixed(2)})`,'#7F8C8D',()=>{WindowUtil.setWindowGrayScale(this.grayScaleValue).then(()=>{this.addLog(`setWindowGrayScale(${this.grayScaleValue.toFixed(2)}) → 成功`);}).catch((e:Error)=>{this.addLog(`Error:${e.message}`);});})this.Btn('setWindowGrayScale(0) 恢复彩色','#95A5A6',()=>{WindowUtil.setWindowGrayScale(0).then(()=>{this.grayScaleValue=0;this.addLog('setWindowGrayScale(0) → 恢复彩色');}).catch((e:Error)=>{this.addLog(`Error:${e.message}`);});})WindowUtil 方法调用时序图
全屏视频场景的调用顺序:
进入全屏 ↓ setWindowLayoutFullScreen(true) // 布局全屏 ↓ setSpecificSystemBarEnabled('status', false, true) // 隐藏状态栏 ↓ setSpecificSystemBarEnabled('navigation', false, true) // 隐藏导航栏 ↓ setPreferredOrientation(LANDSCAPE) // 横屏 ↓ setWindowKeepScreenOn(true) // 屏幕常亮 退出全屏(反向) ↓ setWindowKeepScreenOn(false) ↓ setPreferredOrientation(PORTRAIT) ↓ setSpecificSystemBarEnabled('navigation', true, true) ↓ setSpecificSystemBarEnabled('status', true, true) ↓ setWindowLayoutFullScreen(false)写在最后
WindowUtil 的方法组合使用才是真正的威力所在。
单独一个方法解决不了全屏场景,需要亮度、系统栏、沉浸式、方向、常亮这几个协作,按正确顺序调用,才能做出体验流畅的全屏效果。
建议把进入全屏和退出全屏的操作封装成两个函数,代码更清晰,也不容易遗漏。