【每日学点HarmonyOS Next知识】导航区域高度、截屏录屏监听、设备自旋转、适配挖孔屏、向子窗口传递页面参数
#### 1、HarmonyOS windowClass.getWindowAvoidArea() 方法中导航区域高度是否准确?
通过如下代码,获取底部导航区域的位置信息,拿到的height值是 91,是否是准确的?定值逻辑是什么?
```
const systemArea = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR); console.log("systemArea>>>>>>", JSON.stringify(systemArea))
```
打印结果如下:
```
systemArea>>>>>> {"visible":true,"leftRect":{"left":0,"top":0,"width":0,"height":0},"topRect":{"left":0,"top":0,"width":0,"height":0},"rightRect":{"left":0,"top":0,"width":0,"height":0},"bottomRect":{"left":409,"top":2629,"width":442,"height":91}}
```
目前获取到的91是px。 导航条本身高度为6vp,距离屏幕边缘是10vp。
#### 2、HarmonyOS 如何区分截屏和录屏事件?
`@ohos.window.on(‘screenshot’)`使用该方法监听截屏事件时,用户进行截屏和结束录屏均会触发该事件,请问应该如何区分截屏事件和录屏事件
开启屏幕截屏、投屏、录屏状态变化的监听参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-display-V5#ZH-CN_TOPIC_0000001930756769__displayoncapturestatuschange12
`on(type: 'captureStatusChange', callback: Callback<boolean>): void`
开启屏幕截屏、投屏、录屏状态变化的监听。
**参数:**
| 参数名 | 类型 | 必填 | 说明 |
| :------- | :---------------- | :-- | :------------------------------------------------------------- |
| type | string | 是 | 监听事件,固定为'captureStatusChange'表示设备截屏、投屏或者录屏状态发生变化。 |
| callback | Callback<boolean> | 是 | 回调函数。表示设备截屏、投屏、录屏状态发生变化。true表示设备开始截屏、投屏或者录屏,false表示结束截屏、投屏、录屏。 |
#### 3、HarmonyOS 设备自动旋转?
HarmonyOS设备支持屏幕自动旋转吗?如何监听设备旋转控制页面横竖屏展示
应用设置屏幕自动旋转:在模块配置文件module.json5中给EntryAbility设置"orientation": “auto_rotation_restricted”,再打开手机自动旋转即可。应用中通过window.getLastWindow 获取window实例–>用setPreferredOrientation设置窗口显示方向的属性。通过diplay.on可以监听屏幕状态改变。点击设置了具体方向后,再加上传感器模式判断屏幕方向。demo如下:
```
import window from '@ohos.window';
import display from '@ohos.display';
const TAG = 'foo'
const ORIENTATION: Array<string> = ['垂直','平', '反向垂直', '反向水平']
@Entry
@Component
struct Index {
@State rotation: number = 0
@State message: string = ORIENTATION[this.rotation]
@Watch('setWindowLayOut') @State isLandscape: boolean = false;// 是否横屏状态
aboutToAppear() {
this.setOrientation(1)
let callback = async () => {
let d = await display.getDefaultDisplaySync()
this.rotation = d.rotation
this.message = ORIENTATION[this.rotation]
console.info(TAG, JSON.stringify(d))
}
try {
display.on("change", callback);//监听屏幕状态改变
} catch (exception) {
console.error(TAG, 'Failed to register callback. Code: ' + JSON.stringify(exception));
}
}
setOrientation(type : number) {
try {
window.getLastWindow(getContext(this), (err, data) => { //获取window实例
if (err.code) {
console.error(TAG, 'Failed to obtain the top window. Cause: ' + JSON.stringify(err));
return;
}
let windowClass = data;
console.info(TAG, 'Succeeded in obtaining the top window. Data: ' + JSON.stringify(data));
let orientation : number;
if (type === 1) {
orientation = window.Orientation.AUTO_ROTATION; //设置窗口方向为传感器自动旋转模式。
} else {
orientation = window.Orientation.UNSPECIFIED; //设置窗口方向为传感器锁定。
}
try {
windowClass.setPreferredOrientation(orientation, (err) => {
if (err.code) {
console.error(TAG, 'Failed to set window orientation. Cause: ' + JSON.stringify(err));
return;
}
console.info(TAG, 'Succeeded in setting window orientation.');
});
} catch (exception) {
console.error(TAG, 'Failed to set window orientation. Cause: ' + JSON.stringify(exception));
}
;
});
} catch (exception) {
console.error(TAG, 'Failed to obtain the top window. Cause: ' + JSON.stringify(exception));
}
;
}
setWindowLayOut() {
// 调用该接口手动改变设备横竖屏状态(设置全屏模式,先强制横屏,再加上传感器模式)
window.getLastWindow(getContext(this)).then((windowClass) => {
if (this.isLandscape) {
console.log('设置屏幕横屏')
windowClass.setPreferredOrientation(window.Orientation.AUTO_ROTATION_LANDSCAPE);
} else {
console.log('设置屏幕竖屏')
windowClass.setPreferredOrientation(window.Orientation.AUTO_ROTATION_PORTRAIT);
}
});
}
build() {
Row() {
Column() {
Text(`${this.rotation}`).fontSize(25)
Text(`${this.message}`).fontSize(25)
Button('全屏')
.width(140)
.onClick(() => {
this.isLandscape = !this.isLandscape; // 设置横屏
});
}
.width("100%")
}
.height('100%')
}
}
```
#### 4、HarmonyOS 如何适配挖孔屏?
可以通过使用setWindowLayoutFullScreen接口设置窗口为全屏布局,参考链接:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/application-window-stage-V5#%E4%BD%93%E9%AA%8C%E7%AA%97%E5%8F%A3%E6%B2%89%E6%B5%B8%E5%BC%8F%E8%83%BD%E5%8A%9B
在看视频、玩游戏等场景下,用户往往希望隐藏状态栏、导航栏等不必要的系统窗口,从而获得更佳的沉浸式体验。此时可以借助窗口沉浸式能力(窗口沉浸式能力都是针对应用主窗口而言的),达到预期效果。从API version 10开始,沉浸式窗口默认配置为全屏大小并由组件模块控制布局,状态栏、导航栏背景颜色为透明,文字颜色为黑色;应用窗口调用setWindowLayoutFullScreen接口,设置为true表示由组件模块控制忽略状态栏、导航栏的沉浸式全屏布局,设置为false表示由组件模块控制避让状态栏、导航栏的非沉浸式全屏布局。
开发步骤
1. 获取应用主窗口。
通过getMainWindow接口获取应用主窗口。
2. 实现沉浸式效果。有以下两种方式:
- 方式一:应用主窗口为全屏窗口时,调用setWindowSystemBarEnable接口,设置导航栏、状态栏不显示,从而达到沉浸式效果。
- 方式二:调用setWindowLayoutFullScreen接口,设置应用主窗口为全屏布局;然后调用setWindowSystemBarProperties接口,设置导航栏、状态栏的透明度、背景/文字颜色以及高亮图标等属性,使之保持与主窗口显示协调一致,从而达到沉浸式效果。
3. 加载显示沉浸式窗口的具体内容。
通过loadContent接口加载沉浸式窗口的具体内容。
```
import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage) {
// 1.获取应用主窗口。
let windowClass: window.Window | null = null;
windowStage.getMainWindow((err: BusinessError, data) => {
let errCode: number = err.code;
if (errCode) {
console.error('Failed to obtain the main window. Cause: ' + JSON.stringify(err));
return;
}
windowClass = data;
console.info('Succeeded in obtaining the main window. Data: ' + JSON.stringify(data));
// 2.实现沉浸式效果。方式一:设置导航栏、状态栏不显示。
let names: Array<'status' | 'navigation'> = [];
windowClass.setWindowSystemBarEnable(names)
.then(() => {
console.info('Succeeded in setting the system bar to be visible.');
})
.catch((err: BusinessError) => {
console.error('Failed to set the system bar to be visible. Cause:' + JSON.stringify(err));
});
// 2.实现沉浸式效果。方式二:设置窗口为全屏布局,配合设置导航栏、状态栏的透明度、背景/文字颜色及高亮图标等属性,与主窗口显示保持协调一致。
let isLayoutFullScreen = true;
windowClass.setWindowLayoutFullScreen(isLayoutFullScreen)
.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));
});
let sysBarProps: window.SystemBarProperties = {
statusBarColor: '#ff00ff',
navigationBarColor: '#00ff00',
// 以下两个属性从API Version 8开始支持
statusBarContentColor: '#ffffff',
navigationBarContentColor: '#ffffff'
};
windowClass.setWindowSystemBarProperties(sysBarProps)
.then(() => {
console.info('Succeeded in setting the system bar properties.');
})
.catch((err: BusinessError) => {
console.error('Failed to set the system bar properties. Cause: ' + JSON.stringify(err));
});
})
// 3.为沉浸式窗口加载对应的目标页面。
windowStage.loadContent("pages/page2", (err: BusinessError) => {
let errCode: number = err.code;
if (errCode) {
console.error('Failed to load the content. Cause:' + JSON.stringify(err));
return;
}
console.info('Succeeded in loading the content.');
});
}
};
```
#### 5、HarmonyOS 创建子窗口时,如何向子窗口传递页面参数?
参考demo:
EntryAbility.ets
```
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
// 给Index页面传递windowStage
AppStorage.setOrCreate('windowStage', windowStage);
});
}
```
Index.ets
```
import window from '@ohos.window';
import { BusinessError } from '@ohos.base';
let windowStage_: window.WindowStage | undefined = undefined;
let sub_windowClass: window.Window | undefined = undefined;
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
storage: LocalStorage = new LocalStorage();
private CreateSubWindow(){
// 获取windowStage
windowStage_ = AppStorage.get('windowStage');
// 1.创建应用子窗口。
if (windowStage_ == null) {
console.error('Failed to create the subwindow. Cause: windowStage_ is null');
}
else {
windowStage_.createSubWindow("mySubWindow", (err: BusinessError, data) => {
let errCode: number = err.code;
if (errCode) {
console.error('Failed to create the subwindow. Cause: ' + JSON.stringify(err));
return;
}
sub_windowClass = data;
console.info('Succeeded in creating the subwindow. Data: ' + JSON.stringify(data));
// 2.子窗口创建成功后,设置子窗口的位置、大小及相关属性等。
sub_windowClass.moveWindowTo(300, 300, (err: BusinessError) => {
let errCode: number = err.code;
if (errCode) {
console.error('Failed to move the window. Cause:' + JSON.stringify(err));
return;
}
console.info('Succeeded in moving the window.');
});
sub_windowClass.resize(500, 500, (err: BusinessError) => {
let errCode: number = err.code;
if (errCode) {
console.error('Failed to change the window size. Cause:' + JSON.stringify(err));
return;
}
console.info('Succeeded in changing the window size.');
});
// 3.为子窗口加载对应的目标页面。
this.storage.setOrCreate('storageSimpleProp', 121);
sub_windowClass.loadContent("pages/SubWindow", this.storage, (err: BusinessError) => {
let errCode: number = err.code;
if (errCode) {
console.error('Failed to load the content. Cause:' + JSON.stringify(err));
return;
}
console.info('Succeeded in loading the content.');
// 3.显示子窗口。
(sub_windowClass as window.Window).showWindow((err: BusinessError) => {
let errCode: number = err.code;
if (errCode) {
console.error('Failed to show the window. Cause: ' + JSON.stringify(err));
return;
}
console.info('Succeeded in showing the window.');
});
});
})
}
}
private destroySubWindow(){
// 4.销毁子窗口。当不再需要子窗口时,可根据具体实现逻辑,使用destroy对其进行销毁。
(sub_windowClass as window.Window).destroyWindow((err: BusinessError) => {
let errCode: number = err.code;
if (errCode) {
console.error('Failed to destroy the window. Cause: ' + JSON.stringify(err));
return;
}
console.info('Succeeded in destroying the window.');
});
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button(){
Text('CreateSubWindow')
.fontSize(24)
.fontWeight(FontWeight.Normal)
}.width(220).height(68)
.margin({left:10, top:60})
.onClick(() => {
this.CreateSubWindow()
})
Button(){
Text('destroySubWindow')
.fontSize(24)
.fontWeight(FontWeight.Normal)
}.width(220).height(68)
.margin({left:10, top:60})
.onClick(() => {
this.destroySubWindow()
})
Image($rawfile('[library2].mmm.png'))
}
.width('100%')
}
.height('100%')
}
}
```
更多推荐
所有评论(0)