一、前言
在探索 HarmonyOS 的过程中,我们发现了许多有趣且实用的功能和特性。有些总是在不经意间或者触类旁通的找到。其中,AvoidArea 是窗口内容需要规避区域,也是我们在处理沉浸式、全屏时遇到的。
该系列将着重分享、介绍HarmonyOS API11+的新版本特性或者奇奇怪怪的解决方案、BUG。(弃用API非必要不提及)
如果您有任何疑问、对文章写的不满意、发现错误或者有更好的方法,欢迎在评论、私信或邮件中提出,非常感谢您的支持。🙏
二、沉浸式
和窗口相关的API几乎都在@ohos.window
模块下,直接使用window.setWindowLayoutFullScreen(true)
即可获得一个沉浸式效果。此时布局不避让状态栏与导航栏,组件与其重叠。
一般而言你可以在任何地方使用await window.getLastWindow(getContext())
来获得当前的window
对象,subwindow
不在此列。当然它也有对应的callback写法(但是,是await不好用吗?)
import { BusinessError } from '@ohos.base';
let isLayoutFullScreen = true;
try {
let promise = windowClass.setWindowLayoutFullScreen(isLayoutFullScreen);
promise.then(() => {
console.info('Succeeded in setting the window layout to full-screen mode.');
}).catch((err: BusinessError) => {
console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err));
});
} catch (exception) {
console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(exception));
}
三、全屏
全屏一般是指隐藏NavigationBar和StatusBar,使用setWindowSystemBarEnable
,传入一个空的数组。就可以获得一个光溜溜的界面了。(此时自带沉浸式,毕竟沉浸的地方都没了)
let win = await window.getLastWindow(getContext())
win.setWindowSystemBarEnable([])
目前该方法接收一个数组对象,setWindowSystemBarEnable(names: Array<'status' | 'navigation'>)
,不显示哪个,就不传入哪个便好。
还有一个API,用于单独控制,而且多了一个导航条的控制,但是其表现在API12上,完全不符合预期。所以不做赘述
win.setSpecificSystemBarEnabled("status",false)
win.setSpecificSystemBarEnabled("navigation",false)
win.setSpecificSystemBarEnabled("navigationIndicator",true)
四、AvoidArea
这是正主了,往往沉浸式的时候,需要去处理组件被系统栏盖住的情况。此时你可以使用getWindowAvoidArea(type: AvoidAreaType): AvoidArea
let type = window.AvoidAreaType.TYPE_SYSTEM;
try {
let avoidArea = windowClass.getWindowAvoidArea(type);
} catch (exception) {
console.error('Failed to obtain the area. Cause:' + JSON.stringify(exception));
}
可以看到,接收5种类型。其中TYPE_NAVIGATION_INDICATOR
是为了解决,沉浸式的时候,获取TYPE_SYSTEM
底部规避区域高度为0的BUG,而诞生的新Type。
AvoidArea是一个拥有4个Rect的容器。
值得注意的是:
- 底部手势区域中非导航条区域支持点击、长按事件透传,不支持拖入。
- 左右侧边手势区域支持点击、长按以及上下滑动事件透传,不支持拖入。
- 导航条区域支持长按、点击、拖入事件响应,不支持事件向下透传。
有时候,规避区域是会变化的,监听一下就好了。反过来off解除。
try {
windowClass.on('avoidAreaChange', (data) => {
console.info('Succeeded in enabling the listener for system avoid area changes. type:' +
JSON.stringify(data.type) + ', area: ' + JSON.stringify(data.area));
});
} catch (exception) {
console.error('Failed to enable the listener for system avoid area changes. Cause: ' + JSON.stringify(exception));
}
五、expandSafeArea
这个API是在做自定义键盘面板的时候发现的。实际上它完全可以用来做沉浸式,而且更加的方便,只在加了的地方生效,而不像window直接生效在整个页面。
使用起来也很简单,直接在根组件(任意组件都行)
build() {
Column() {
Column() {
}
.width('100%')
.height('100%')
}
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM,SafeAreaEdge.TOP])
.backgroundColor(Color.Orange)
.size({ width: '100%', height: '100%' })
}
此时,和window.setWindowLayoutFullScreen(true)
的效果是一模一样的。
哦,这个要API 11。
六、预告
下篇分享点击(可能)
七、结尾
没了。
如果您有任何疑问、对文章写的不满意、发现错误或者有更好的方法,欢迎在评论、私信或邮件中提出,非常感谢您的支持。🙏