HarmonyOS:应用横竖屏切换

一、概述

当前HarmonyOS应用开发主要通过以下两种方式实现视频横竖屏切换:

  • 设置窗口的旋转策略,旋转整个窗口。
  • 跳转到不同显示方向的页面,仅旋转子页面。

二、窗口旋转说明

目前HarmonyOS系统中的窗口旋转形态有四种,对应真机实际状态如下:


开发者可通过以下两种方式设置窗口旋转策略:

  • 通过module.json5文件中的"orientation"字段进行设置。

  • 调用窗口管理的setPreferredOrientation()接口进行设置。
    说明 上述两种方式设置窗口旋转策略的时机不同。

  • module.json5文件中的"orientation"字段在窗口启动时就会生效,通常用于应用启动时就需要设置横屏或者竖屏的场景。

  • setPreferredOrientation() 接口在调用时进行窗口方向的设置,通常用于在应用启动之后,还需要改变显示方向的场景。

2.1 配置module.json5文件中的orientation字段

orientation字段用于配置应用启动时的窗口显示状态。如果应用启动时需要以默认的横屏或竖屏方式显示,建议在此字段进行相应配置。其支持的参数可参考module.json5配置项中abilities标签下的orientation字段说明。

示例代码

c 复制代码
{
  "module": {
    // ...
    "abilities": [
      {
        "name": "EntryAbility",
        // ...
        // Set default window orientation
        "orientation": "portrait",
        // ...
      }
    ],
    // ...
    "requestPermissions": [
      {
        "name": "ohos.permission.ACCELEROMETER"
      }
    ]
  }
}

开发者可根据应用的默认旋转行为配置orientation字段:

  • 如果应用是竖屏应用,建议配置portrait为默认旋转策略。
  • 如果应用是横屏应用(如游戏类应用),启动时默认为横屏,存在以下两种情况:
    • 仅支持横屏,建议配置landscape为默认旋转策略。
    • 支持在横屏和反向横屏中切换,建议配置为auto_rotation_landscape。
  • 如果应用是可旋转应用,建议配置auto_rotation_restricted为默认旋转策略。
  • 如果一个应用在直板机和折叠屏折叠态为竖屏应用,在平板和折叠屏展开态默认为可旋转应用,建议配置follow_desktop为默认旋转策略。
    注意 对于需要通过控制中心进行旋转锁定控制的场景,可选择带有"restricted"后缀的旋转策略。带有此后缀的字段表示旋转行为受控制中心的旋转锁定开关控制:当旋转锁定开关开启时,窗口不会随传感器旋转;关闭时,窗口将随传感器旋转。
    以如下应用为例,关闭控制中心的旋转锁定开关后,应用页面会随手机旋转而切换;开启旋转锁定开关后,则不会发生切换。需将orientation字段配置为auto_rotation_restricted以实现此效果。

三、调用窗口管理的setPreferredOrientation()接口

对于需要实现横竖屏切换的应用,可调用setPreferredOrientation()接口进行设置。典型场景包括视频类和图片类应用,视频类应用实现横竖屏切换的效果图如下:

效果图

竖屏展示

横屏展示

四、通过窗口旋转实现横竖屏切换

为了实现应用的横竖屏功能,需从以下技术方面考虑:

  1. 设置窗口的旋转策略。
  2. 监听屏幕的窗口变化。
  3. 进行布局适配。

4.1 设置窗口的旋转策略

首先需要设置应用启动时的旋转策略,具体可以参考配置module.json5文件中的orientation字段。以多设备开发为例,为满足直板机和平板设备的不同策略,可将orientation字段设置为follow_desktop。
在需要实现横竖屏切换的页面上,可调用窗口管理提供的setPreferredOrientation()接口,将窗口显示的方向修改为横屏或竖屏的状态。例如,视频播放页面既支持竖屏,也支持横屏,可调用此接口实现横竖屏切换。
在使用setPreferredOrientation()接口时,应根据应用自身的旋转策略选择相应的参数,可封装如下方法以设置旋转策略。具体步骤如下:

  1. 通过this.getUIContext().getHostContext()接口获取对应的UIAbilityContext,并通过context获取对应的windowStage实例。
  2. 通过windowStage.getMainWindowSync()同步接口获取对应的窗口实例windowClass,再调用setPreferredOrientation()接口设置窗口方向。

示例代码 TestOrientation.ets文件代码

c 复制代码
import { window } from '@kit.ArkUI';
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@ComponentV2
struct TestOrientation {
  private windowClass: window.Window | undefined;
  private context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  // currentOrientation 注意默认方向需要和 module.json5配置项中abilities标签下的orientation字段方向一致
  private currentOrientation = window.Orientation.USER_ROTATION_PORTRAIT
  @Local message: string = '应用横竖屏切换';
  @Local btnText: string = "设置为横屏"
  @Local currentOrientationText: string = "当前是竖屏展示"

  aboutToAppear(): void {
    try {
      this.windowClass = this.context.windowStage.getMainWindowSync();
    } catch (error) {
      let err = error as BusinessError;
      console.log("获取 windowClass 异常" + err.message + " , err.code:" + err.code)
    }
  }

  setOrientation(orientation: window.Orientation) {
    this.windowClass?.setPreferredOrientation(orientation).then(() => {
      console.info(`设置屏幕方向 setWindowOrientation ${orientation} Succeeded`);
    }).catch((err: BusinessError) => {
      let error = err as BusinessError;
      console.error(`设置屏幕方向 异常 setWindowOrientation ${orientation} err, code: ${error.code}, message: ${error.message}`);
    })
  }

  build() {
    Column({ space: 20 }) {
      Text(this.message)
        .id('TestOrientationHelloWorld')
        .fontSize($r('app.float.text_size_20fp'))
        .margin({ top: 40 })

      Text(this.currentOrientationText)
        .fontSize($r('app.float.text_size_20fp'))

      Button(this.btnText)
        .onClick(() => {
          //临时旋转到竖屏,之后恢复自动旋转(受控制中心旋转开关控制), 随传感器旋转
          if (this.currentOrientation === window.Orientation.USER_ROTATION_LANDSCAPE) {
            this.btnText = "设置为横屏"
            this.currentOrientationText = "当前是竖屏展示"
            this.currentOrientation = window.Orientation.USER_ROTATION_PORTRAIT
          } else {
            this.btnText = "设置为竖屏"
            this.currentOrientationText = "当前是横屏展示"
            this.currentOrientation = window.Orientation.USER_ROTATION_LANDSCAPE
          }

          //固定竖屏,设置后窗口始终保持竖屏方向,不随传感器旋转
          // if (this.currentOrientation === window.Orientation.LANDSCAPE) {
          //   this.btnText = "设置为横屏"
          //   this.currentOrientationText = "当前是竖屏展示"
          //   this.currentOrientation = window.Orientation.PORTRAIT
          // } else {
          //   this.btnText = "设置为竖屏"
          //   this.currentOrientationText = "当前是横屏展示"
          //   this.currentOrientation = window.Orientation.LANDSCAPE
          // }

          this.setOrientation(this.currentOrientation)
        })

    }
    .height('100%')
    .width('100%')
  }
}

以视频播放为例,不仅需要通过设备旋转方向控制横竖屏,还需在旋转锁定开关开启时,支持用户手动设置横屏状态。若开发者需实现以上效果,应满足以下条件:

  1. 应用跟随传感器旋转。
  2. 应用受到控制中心的旋转锁定开关控制。
  3. 应用支持用户临时设置窗口方向,例如:点击全屏按钮进行切换。

如果应用满足上述条件,可使用窗口管理的setPreferredOrientation()接口设置orientation的枚举类型,以实现相应的旋转。当用户手动点击全屏按钮时,需触发横竖屏切换。如果此时关闭旋转锁定开关,窗口将随传感器旋转。因此,可使用以下枚举中的能力,临时旋转窗口,并使其后续跟随传感器自动旋转。

orientation部分参数列举

orientation枚举值 枚举数值 效果描述
USER_ROTATION_PORTRAIT 13 调用时临时旋转到竖屏,之后跟随传感器自动旋转,受控制中心的旋转开关控制,且可旋转方向受系统判定。
USER_ROTATION_LANDSCAPE 14 调用时临时旋转到横屏,之后跟随传感器自动旋转,受控制中心的旋转开关控制,且可旋转方向受系统判定。

五、NavDestination 设置窗口方向

preferredOrientation API 19 preferredOrientation(orientation: Optional<Orientation>)

设置NavDestination对应的显示方向。转场到该NavDestination后,系统也会将应用主窗口切到该显示方向。
说明 该属性满足如下全部条件时才有效:

  • NavDestination属于应用主窗口页面,并且主窗口为全屏窗口;
  • NavDestination所属的Navigation的大小占满整个应用页面;
  • NavDestination类型为NavDestinationMode.STANDARD。

设置显示方向的实际效果依赖于具体的设备支持情况,具体参考窗口的setPreferredOrientation接口。
元服务API : 从API version 19开始,该接口支持在元服务中使用。

模型约束 : 此接口仅可在Stage模型下使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数

参数名 类型 必填 说明
orientation Optional<Orientation> NavDestination页面对应的Orientation。
相关推荐
颜颜yan_1 小时前
ESP-IDF 鸿蒙 PC 适配全记录:打通 Python、构建工具链与 ESP32-P4 固件生成
python·华为·harmonyos
梦想不只是梦与想4 小时前
鸿蒙 邀请测试:AppGallery邀请测试流程
harmonyos·appgallery 邀请测试·邀请测试
贾伟康7 小时前
【口算王|02】HarmonyOS ArkTS 答题提交实战:防止重复提交并推进下一题
harmonyos·arkts·状态管理·arkui·幂等设计
承渊政道9 小时前
Python IDLE鸿蒙PC适配全记录:从Tkinter桌面程序到ArkUI原生开发闭环
开发语言·python·harmonyos·鸿蒙系统·桌面程序
万物智能信息科技9 小时前
电容触摸 FT5406,另一颗芯片、同一条总线—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
人工智能·华为·开源·harmonyos·鸿蒙
ChinaDragonDreamer9 小时前
HarmonyOS:应用程序包管理模块(获取当前应用信息)
harmonyos·鸿蒙
●VON9 小时前
Flutter 鸿蒙插件适配实战:用 boot_time_plugin 1.0.0 读取启动时间与运行时长
flutter·华为·harmonyos
颜颜yan_10 小时前
Git Cola 鸿蒙 PC 版适配全记录:从 Qt 桌面工具到 ArkTS 原生应用
git·qt·harmonyos
承渊政道11 小时前
Python IDLE鸿蒙PC适配全记录:用 ArkUI 重建编辑、运行、Shell 与基础调试闭环
python·microsoft·harmonyos·鸿蒙系统·pc端