当前位置: 首页 > news >正文

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.Orientation
(1)全局固定方向(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,使应用跟随设备方向旋转)。

实现方案

系统为设备窗口尺寸变化监听、设置应用子窗尺寸和位置提供了如下接口:

  1. on('windowSizeChange')接口用于开启窗口尺寸变化的监听,当窗口发生旋转后,会触发其中的回调。
  2. resize()接口用于改变当前窗口的大小,可以在窗口发生旋转后及时调整子窗的宽高。
  3. 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", // ... } ], // ... } }

该场景下多窗布局动态可变为横向,需要配合API(enableLandscapeMultiWindow()/ disableLandscapeMultiWindow())使用。

private windowClass = (this.getUIContext().getHostContext() as common.UIAbilityContext).windowStage.getMainWindowSync() aboutToAppear(): void { this.windowClass.enableLandscapeMultiWindow(); } aboutToDisappear(): void { this.windowClass.disableLandscapeMultiWindow(); }
实现效果:

附:

文章部分参考wiki:

设置屏幕朝向 orientation (横竖屏) | 华为开发者联盟

http://www.cnnetsun.cn/news/3073174.html

相关文章:

  • 二升三年级暑假特色作业(pdf图文版)
  • 斯坦福CS146S课程 提示词工程全解(第1周):6大核心技术从原理到代码实战
  • 如何将VR视频转换为2D格式:VR-Reversal完整指南
  • MySQL数据分析入门:从SQL查询到实战电商案例全解析
  • 基于HarmonyOS 7.0 跨端开发的篆刻印章设计页面实战
  • 基于HarmonyOS 7.0 跨端开发的化石猎人采集指南页面实战
  • TVA与具身智能深度融合的内在必然性(7)
  • 从Vgs到VCO:用拉扎维《模拟CMOS》的核心概念,手把手拆解一个PLL设计流程
  • Sunshine游戏串流服务器:打造你的终极跨平台游戏串流系统
  • 量子机器学习在湍流模拟中的创新应用
  • 设计高可用后端架构需要考虑的五个关键点
  • 单通道EEG实现非侵入式脑机接口图像重建技术
  • 终极GPU内存检测方案:MemtestCL专业显卡稳定性验证指南
  • 30天无限续杯:JetBrains IDE试用期重置的完整指南
  • 面向Shopify卖家的最佳AI营销工具栈:选对组合,提升广告转化率
  • 网络安全学习130天
  • 树莓派5到手第一步:保姆级Ubuntu 24.04 Server无头安装与SSH配置(含阿里云镜像加速)
  • Steam Deck模拟器终极指南:如何用EmuDeck一键搭建30+游戏平台
  • 模块化脑机接口系统设计与工程实践
  • 量子误差缓解技术:从噪声建模到PEC实现
  • 自动化诊断平台架构与MTTR优化实践
  • 量子计算在热化学中的应用与W4-11数据集分析
  • 量子计算在化学模拟中的革命性应用与挑战
  • 边缘AI计算新突破:超维计算芯片解析与应用
  • FPGA加速稀疏卷积:原理、实现与性能优化
  • MySQL数据分析入门:从零搭建环境到电商实战案例
  • DAY3 编码器接口
  • Yahoo Finance API:构建企业级金融数据解决方案的.NET实践指南
  • 4步让老旧Mac焕发新生:OpenCore Legacy Patcher终极指南
  • 前后端分离公益服务平台系统|SpringBoot+Vue+MyBatis+MySQL完整源码+部署教程