window.setMainWindowOrientation 设置横竖屏切换,为什么没有切换完成后的监听?

0 评论 293 浏览 0 收藏 12 分钟

本问答帖原创发布在华为开发者联盟社区 ,欢迎开发者前往论坛提问交流。

更多与该问题相关的讨论,请点击原帖查看:

window.setMainWindowOrientation 设置横竖屏切换,为什么没有切换完成后的监听?-华为开发者问答 | 华为开发者联盟 (huawei.com)

问题描述:

window.setMainWindowOrientation 设置横竖屏切换,为什么没有切换完成后的监听?

解决方案:

【背景知识】

【解决方案】

import window from '@ohos.window';

import display from '@ohos.display';




const ORIENTATION: Array<string> = ['垂直', '平', '反向垂直', '反向水平']

@Entry

@Component

struct OrientationPage {

@State rotation: number = 0

@State message: string = ORIENTATION[this.rotation]

// 是否横屏状态

@State @Watch('setWindowLayOut') isLandscape: boolean = false;

aboutToAppear() {

// 监听屏幕状态改变

display.on("change", async () => {

// 获取当前旋转角度

this.rotation = await display.getDefaultDisplaySync().rotation

this.message = ORIENTATION[this.rotation]

});

}

setWindowLayOut() {

// 调用该接口手动改变设备横竖屏状态(设置全屏模式,先强制横屏,再加上传感器模式)

window.getLastWindow(getContext(this)).then((windowClass) => {

if (this.isLandscape) {

// 设置屏幕横屏

windowClass.setPreferredOrientation(window.Orientation.AUTO_ROTATION_LANDSCAPE);

} else {

// 设置屏幕竖屏

windowClass.setPreferredOrientation(window.Orientation.AUTO_ROTATION_PORTRAIT);

}

});

}

build() {

Row() {

Column() {

Text(`${this.rotation}`)

.fontSize(25)

Text(`${this.message}`)

.fontSize(25)

Button(this.isLandscape ? '竖屏' : '横屏')

.width(140)

.onClick(() => {

// 设置横屏

this.isLandscape = !this.isLandscape;

});

}

.width("100%")

}

.height('100%')

}

}
  • 可在EntryAbility的onWindowStageCreate中注册windowsSizeChange事件,并通过AppStorage存储,在页面中通过StorageLink监听数据的变换实现屏幕旋转的监听,可参考以下示例:
// EntryAbility.ets

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';

import { hilog } from '@kit.PerformanceAnalysisKit';

import { display, window } from '@kit.ArkUI';




export default class EntryAbility extends UIAbility {

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {

hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');

}




onDestroy(): void {

hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');

}




onWindowStageCreate(windowStage: window.WindowStage): void {




hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');




let mainWindow: window.Window;

try {

mainWindow = windowStage.getMainWindowSync();

let displayClass: display.Display = display.getDefaultDisplaySync();

AppStorage.setOrCreate('orientation', displayClass.orientation);

// 监听窗口的windowsSizeChange事件,旋转屏时会触发该事件

mainWindow.on('windowSizeChange', (data) => {

let displayClass: display.Display | null = null;

try {

displayClass = display.getDefaultDisplaySync();

// 获取屏幕的显示方向

AppStorage.set('orientation', displayClass.orientation);

} catch {

return;

}

})

} catch {

hilog.info(0x0000, 'testTag', '%{public}s', 'error');

return;

}




windowStage.loadContent('pages/Index', (err) => {

if (err.code) {

return;

}

hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');

});

}




onWindowStageDestroy(): void {

// Main window is destroyed, release UI related resources

hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');

}




onForeground(): void {

// Ability has brought to foreground

hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');

}




onBackground(): void {

// Ability has back to background

hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');

}

}




```

- 页面中通过StorageLink监听数据的变换实现屏幕旋转的监听:

```ts

// index.ets

import { display } from '@kit.ArkUI';




@Entry

@Component

struct Index {

// 获取通过监听窗口的windowsSizeChange事件得到的屏幕显示方向

@StorageLink('orientation') myOrientation: display.Orientation = 0;




build() {

Stack() {

// 当屏幕显示方向变化时,切换组件的视图效果

if (this.myOrientation == 0 ||

this.myOrientation == 2) {

Image($r('app.media.startIcon'))

.size({ width: 100, height: 100 })

.id('image1')

} else {

Image($r('app.media.background'))

.position({ x: 0, y: 0 })

.size({ width: 200, height: 200 })

.id('image2')

}

}

.backgroundColor(Color.White)

.size({ width: '100%', height: '100%' })

}

}

需要在项目的module.json5文件中的abilities列表里添加"orientation",指定为"auto_rotation":

{

"module": {

// ...

"abilities": [

{

// ...

"orientation": "auto_rotation",

}

],

}

}
  • 通过设备中的重力传感器,可以检测该设备在三个坐标轴(即X轴、Y轴及Z轴)上的线性加速度。基于这些数据,能够推算出屏幕当前的旋转状态。有关具体实现方式,可参考以下示例:
import sensor from '@ohos.sensor';

import base from '@ohos.base';

@Entry

@Component

struct OrientationPage {

@State rotation: string = 'INVALID'

onDegree(callback: base.Callback<string>): void {

sensor.on(sensor.SensorId.GRAVITY, (data: sensor.GravityResponse) => {

let degree: number = -1;

degree = this.CalDegree(data.x, data.y, data.z)

console.log(degree + "zzz")

if (degree >= 0 && (degree <= 30 || degree >= 330)) {

this.rotation = "ROTATION_0";

} else if (degree >= 60 && degree <= 120) { // Use ROTATION_90 when degree range is [60, 120]

this.rotation = "ROTATION_90";

} else if (degree >= 150 && degree <= 210) { // Use ROTATION_180 when degree range is [150, 210]

this.rotation = "ROTATION_180";

} else if (degree >= 240 && degree <= 300) { // Use ROTATION_270 when degree range is [240, 300]

this.rotation = "ROTATION_270";

}

callback(this.rotation);

});

}

CalDegree(x: number, y: number, z: number): number {

let degree: number = -1;

// 3为有效_增量_角度_阈值_系数

if ((x * x + y * y) * 3 < z * z) {

return degree;

}

degree = 90 - (Number)(Math.round(Math.atan2(y, -x) / Math.PI * 180));

return degree >= 0 ? degree % 360 : degree % 360 + 360;

}

aboutToAppear() {

let callback = async (rotation: string) => {

console.log('rotation = ' + rotation)

}

try {

this.onDegree(callback);

} catch (exception) {

}

}

build() {

Row() {

Column() {

Text(`${this.rotation}`)

.fontSize(25)

}

.width("100%")

}

.height('100%')

}

}
  • 使用媒体查询接口监听屏幕旋转,设置媒体查询的查询条件为屏幕的方向,可选值为orientation:portrait(设备竖屏)和orientation: landscape(设备横屏)。有关具体实现方式,可参考以下示例:
import { mediaquery } from '@kit.ArkUI';

// 监听横屏事件

let listener = mediaquery.matchMediaSync('(orientation: portrait)');

function onPortrait(mediaQueryResult: mediaquery.MediaQueryResult) {

if (mediaQueryResult.matches) {

console.log(`横屏`)

} else {

}

}

// 注册回调

listener.on('change', onPortrait)

// 取消注册回调

listener.off('change', onPortrait)

【总结】

除可在module.json5文件中全局配置当前UIAbility组件启动时的方向之外,亦可通过调用window.setPreferredOrientation方法动态设定特定页面的窗口方向,请根据具体的业务场景选择合适的方案来监听屏幕旋转事件。

 

▶更多实践干货就在华为开发者联盟

▶扫码加入鸿蒙主题交流群,共同交流鸿蒙应用创新与开发

 

更多精彩内容,请关注人人都是产品经理微信公众号或下载App
评论
评论请登录
  1. 目前还没评论,等你发挥!