一、概述
当前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()接口进行设置。典型场景包括视频类和图片类应用,视频类应用实现横竖屏切换的效果图如下:
效果图
竖屏展示
横屏展示
四、通过窗口旋转实现横竖屏切换
为了实现应用的横竖屏功能,需从以下技术方面考虑:
- 设置窗口的旋转策略。
- 监听屏幕的窗口变化。
- 进行布局适配。
4.1 设置窗口的旋转策略
首先需要设置应用启动时的旋转策略,具体可以参考配置module.json5文件中的orientation字段。以多设备开发为例,为满足直板机和平板设备的不同策略,可将orientation字段设置为follow_desktop。
在需要实现横竖屏切换的页面上,可调用窗口管理提供的setPreferredOrientation()接口,将窗口显示的方向修改为横屏或竖屏的状态。例如,视频播放页面既支持竖屏,也支持横屏,可调用此接口实现横竖屏切换。
在使用setPreferredOrientation()接口时,应根据应用自身的旋转策略选择相应的参数,可封装如下方法以设置旋转策略。具体步骤如下:
- 通过this.getUIContext().getHostContext()接口获取对应的UIAbilityContext,并通过context获取对应的windowStage实例。
- 通过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%')
}
}
以视频播放为例,不仅需要通过设备旋转方向控制横竖屏,还需在旋转锁定开关开启时,支持用户手动设置横屏状态。若开发者需实现以上效果,应满足以下条件:
- 应用跟随传感器旋转。
- 应用受到控制中心的旋转锁定开关控制。
- 应用支持用户临时设置窗口方向,例如:点击全屏按钮进行切换。
如果应用满足上述条件,可使用窗口管理的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。 |




