HarmonyOs开发--设置屏幕朝向 orientation (横竖屏场景)

📅 2026/6/30 22:13:51
HarmonyOs开发--设置屏幕朝向 orientation (横竖屏场景)
前言最近做了一个HarmonyOs的游戏应用涉及屏幕的朝向问题发现很多不明白的地方这里对屏幕朝向做个总结.希望其他开发者可以得到启发.配置方式HarmonyOS应用在设置屏幕朝向横竖屏时主要有两种方式静态配置全局默认和动态代码控制运行时手动切换场景覆盖主要固定方向、自动旋转、页面的切换等场景的使用。一、静态配置应用默认方向应用级配置配置地方entry/src/main/module.json5使用场景设置应用启动固定方向{ module: { abilities: [ { name: EntryAbility, // 主要配置 orientation: portrait, } ] } }orientation 可选值一共有18个可参考下面官方链接文档Orientation取值https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-window-e#orientation9主要常用的可选值portrait固定竖屏手机应用最常用landscape固定横屏主要用于游戏auto_rotation自动旋转跟随传感器不受系统锁定影响auto_rotation_restricted受系统锁定控制用户开 “自动旋转” 才转follow_desktop跟随设备类型平板 / 手机自动适配unspecified未指定由系统决定选值建议若应用在直板机和双折叠折叠态是竖屏应用平板和双折叠展开态是可旋转应用推荐配置FOLLOW_DESKTOP为默认旋转策略。若应用为竖屏应用建议配置PORTRAIT为默认旋转策略。若应用为横屏应用如MOBA类游戏启动时默认为横屏存在以下两种情况仅支持横屏时建议配置LANDSCAPE为默认旋转策略支持横屏和反向横屏切换时建议配置AUTO_ROTATION_LANDSCAPE或AUTO_ROTATION_LANDSCAPE_RESTRICTED是否受控制中心旋转开关控制。若应用为可旋转应用建议配置AUTO_ROTATION_RESTRICTED为默认旋转策略。二、动态代码控制运行时切换代码控制即窗口级配置核心接口获取窗口window.getLastWindow(context)或windowStage.getMainWindowSync()设置方向setPreferredOrientation(orientation)方向枚举window.Orientation1全局固定方向EntryAbility.ets应用启动时强制锁定方向import { UIAbility } from kit.AbilityKit; import { window } from kit.ArkUI; export default class EntryAbility extends UIAbility { onWindowStageCreate(windowStage: window.WindowStage): void { // 1. 获取主窗口 const mainWindow windowStage.getMainWindowSync(); // 2. 强制固定为竖屏 mainWindow.setPreferredOrientation(window.Orientation.PORTRAIT) .catch((err) { console.error(设置方向失败:, err); }); // 加载页面 windowStage.loadContent(pages/Index); } }2页面级切换A 页面竖屏 → B 页面横屏 → 返回 A 恢复竖屏// VideoPage.ets横屏页面 import { window } from kit.ArkUI; import { common } from kit.AbilityKit; Entry Component struct VideoPage { private context getContext(this) as common.UIAbilityContext; private lastOrientation?: window.Orientation; // 保存原方向 // 页面显示时 → 切横屏 async aboutToAppear() { const win await window.getLastWindow(this.context); // 保存当前方向 this.lastOrientation win.getPreferredOrientation(); // 强制横屏 await win.setPreferredOrientation(window.Orientation.LANDSCAPE); } // 页面消失时 → 恢复原方向 async aboutToDisappear() { const win await window.getLastWindow(this.context); if (this.lastOrientation) { await win.setPreferredOrientation(this.lastOrientation); } } build() { Column() { Text(视频页强制横屏) .fontSize(30) } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) } }3按钮手动切换横竖屏Entry Component struct OrientationDemo { private context getContext(this) as common.UIAbilityContext; // 切换为竖屏 async setPortrait() { const win await window.getLastWindow(this.context); await win.setPreferredOrientation(window.Orientation.PORTRAIT); } // 切换为横屏 async setLandscape() { const win await window.getLastWindow(this.context); await win.setPreferredOrientation(window.Orientation.LANDSCAPE); } // 开启自动旋转 async setAutoRotation() { const win await window.getLastWindow(this.context); await win.setPreferredOrientation(window.Orientation.AUTO_ROTATION); } build() { Column({ space: 20 }) { Button(固定竖屏) .onClick(() this.setPortrait()); Button(固定横屏) .onClick(() this.setLandscape()); Button(自动旋转) .onClick(() this.setAutoRotation()); } .width(100%) .height(100%) .justifyContent(FlexAlign.Center); } }三、其他旋转配置应用子窗口的旋转在应用旋转场景中应用主窗的尺寸由系统控制而应用子窗的尺寸和位置由应用控制。因此建议应用开发者在有应用子窗的旋转场景中同步调整应用子窗的尺寸和位置避免因旋转过程中应用子窗的尺寸和位置保持不变而导致如下图所示的应用子窗显示截断问题直板机默认的旋转策略为UNSPECIFIED旋转锁定按钮关闭的情况下不允许应用旋转可以通过module.json5配置文件中abilities标签的orientation字段配置应用的旋转策略为AUTO_ROTATION使应用跟随设备方向旋转。实现方案系统为设备窗口尺寸变化监听、设置应用子窗尺寸和位置提供了如下接口on(windowSizeChange)接口用于开启窗口尺寸变化的监听当窗口发生旋转后会触发其中的回调。resize()接口用于改变当前窗口的大小可以在窗口发生旋转后及时调整子窗的宽高。moveWindowTo()接口用于移动窗口位置可以在窗口发生旋转后及时调整子窗的位置。为实现根据应用旋转方向设置应用子窗尺寸开发者可使用on(windowSizeChange)接口监听窗口尺寸的变化并在回调函数中通过resize()接口和moveWindowTo()接口分别调整应用子窗的尺寸和位置。需要指出的是开发者可以使用setFollowParentWindowLayoutEnabled()接口设置子窗或模态窗口的布局信息是否跟随主窗如果设置为跟随主窗那么子窗的旋转便不再需要额外适配。import { window } from kit.ArkUI; import { BusinessError } from kit.BasicServicesKit; import { hilog } from kit.PerformanceAnalysisKit; const SUB_WINDOW_LEFT_OFFSET: number 50; const SUB_WINDOW_TOP_OFFSET: number 500; const TAG: string subWindowAdaptWhenRotate; const DOMAIN: number 0x0000; Entry Component struct Index { public mainWindow: window.Window | undefined undefined; public subWindow: window.Window | undefined undefined; aboutToAppear(): void { // create subWindow this.createSubWindow(); this.mainWindow AppStorage.get(mainWindow); if (!this.mainWindow) { return; } this.mainWindow.on(windowSizeChange, () { this.adjustSubwindowSizeAndPosition(); }) } private adjustSubwindowSizeAndPosition(): void { if (!this.subWindow) { hilog.error(DOMAIN, TAG, subWindow is null); return; } let subwindowRect: window.Rect | null null; try { subwindowRect this.subWindow.getWindowProperties().windowRect; } catch (error) { hilog.warn(0x000, testTag, getWindowProperties failed, code: ${error.code}, message: ${error.message}); } let newWidth: number subwindowRect!.height; let newHeight: number subwindowRect!.width; let newX: number subwindowRect!.top; let newY: number subwindowRect!.left; this.subWindow.resize(newWidth, newHeight) .then(() { hilog.info(DOMAIN, TAG, Succeeded in changing the window size) }).catch((err: BusinessError) { hilog.error(DOMAIN, TAG, Failed to change the window size. Cause code: ${err.code}, message: ${err.message}); }); this.subWindow.moveWindowTo(newX, newY) .then(() { hilog.info(DOMAIN, TAG, Succeeded in moving the window); }).catch((err: BusinessError) { hilog.error(DOMAIN, TAG, Failed to move the window. Cause code: ${err.code}, message: ${err.message}); }); } // ... }悬浮窗的旋转悬浮窗默认是竖向的但是对于横向游戏和视频应用横向的悬浮窗体验会更好。开发者可以通过在module.json5配置文件中abilities标签下的preferMultiWindowOrientation属性增加“landscape”或者“landscape_auto”配合API以声明应用支持横向悬浮窗或上下分屏模式。{ module: { // ... abilities: [ { name: EntryAbility, // ... preferMultiWindowOrientation: landscape_auto, // ... } ], // ... } }该场景下多窗布局动态可变为横向需要配合APIenableLandscapeMultiWindow()/ disableLandscapeMultiWindow()使用。private windowClass (this.getUIContext().getHostContext() as common.UIAbilityContext).windowStage.getMainWindowSync() aboutToAppear(): void { this.windowClass.enableLandscapeMultiWindow(); } aboutToDisappear(): void { this.windowClass.disableLandscapeMultiWindow(); }实现效果附文章部分参考wiki:设置屏幕朝向 orientation 横竖屏 | 华为开发者联盟