window.setMainWindowOrientation 设置横竖屏切换,为什么没有切换完成后的监听? 官方
头像 鸿蒙小助手 2026-04-14 16:00:54    发布
5221 浏览 51 点赞 1 收藏

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

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

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方法动态设定特定页面的窗口方向,请根据具体的业务场景选择合适的方案来监听屏幕旋转事件。


©本站发布的所有内容,包括但不限于文字、图片、音频、视频、图表、标志、标识、广告、商标、商号、域名、软件、程序等,除特别标明外,均来源于网络或用户投稿,版权归原作者或原出处所有。我们致力于保护原作者版权,若涉及版权问题,请及时联系我们进行处理。
分类
HarmonyOS
头像

鸿蒙小助手

致力于为鸿蒙开发者谋福利

1031

帖子

7

提问

13565

粉丝

关注
最新发布

MCP+Rules:AI辅助鸿蒙应用开发实践

2026-04-17 10:25:25    发布
热门推荐
地址:北京市朝阳区北三环东路三元桥曙光西里甲1号第三置业A座1508室 商务内容合作QQ:2291221 电话:13391790444或(010)62178877
版权所有:电脑商情信息服务集团 北京赢邦策略咨询有限责任公司
声明:本媒体部分图片、文章来源于网络,版权归原作者所有,我司致力于保护作者版权,如有侵权,请与我司联系删除

京ICP备:2022009079号-2

京公网安备:11010502051901号

ICP证:京B2-20230255