# 18.4:横竖屏切换
我们在应用开发的过程中,可能会遇见横竖屏切换的场景,比如视频类应用在播放视频的时候有切换横屏的场景。本节笔者简单介绍一下横竖屏切换在 FA 模型和 State 模型下的两种实现方式。
# 18.4.1:FA模型实现
在 FA 模型下实现横竖屏比较简单,直接使用 @ohos.ability.featureAbility
的 getContext() 方法获取一个 Conetxt
,然后调用该 Context
的 setDisplayOrientation() 方法即可,示例代码如下:
import featureAbility from '@ohos.ability.featureAbility';
import bundle from '@ohos.bundle';
@Entry @Component struct ArkUIClubTest {
private portrait: boolean = true
build() {
Stack() {
Button("横竖屏切换")
.onClick(() => {
this.changeOrientation()
})
}
.width('100%')
.height('100%')
}
private changeOrientation() {
if (this.portrait) {
// 切换成横屏
featureAbility.getContext().setDisplayOrientation(bundle.DisplayOrientation.LANDSCAPE).then(() => {
console.log("setDisplayOrientation success")
this.portrait = !this.portrait
}).catch((error) => {
console.log("setDisplayOrientation error: " + JSON.stringify(error))
})
} else {
// 切换成竖屏
featureAbility.getContext().setDisplayOrientation(bundle.DisplayOrientation.PORTRAIT).then(() => {
console.log("setDisplayOrientation success")
this.portrait = !this.portrait
}).catch((error) => {
console.log("setDisplayOrientation error: " + JSON.stringify(error))
})
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
样例运行结果如下图所示:
# 18.4.2:Stage模型实现
OpenHarmony 在 API 9 上提供了不同于 FA 模型的 Stage 开发模型,Stage 模型的设计基于 为复杂应用而设计, 支持多设备和多窗口形态 , 平衡应用能力 和 系统管控成本 为出发点而设计出来的。
在 Stage 模型下,可以通过 Window
对象的 setPreferredOrientation() 方法实现横竖屏切换,笔者梳理了以下三种方式:
通过getLastWindow() 方法
通过
@ohos.window
模块的 getLastWindow() 方法获取Window
对象时需要一个Context
对象作为参数,该对象可在MainAbility
的 onCreate() 方法中获取,实现步骤如下所示:保存 AbilityContext 对象
import hilog from '@ohos.hilog' import Ability from '@ohos.application.Ability' import Window from '@ohos.window' export default class MainAbility extends Ability { onCreate(want, launchParam) { // 通过globalThis保存context globalThis.abilityContext = this.context } // 省略部分代码 }
1
2
3
4
5
6
7
8
9
10
11获取 Window 对象
private changeOrientation() { // 拿到globalThis保存的context var context = globalThis.abilityContext as Context // 调用 `@ohos.window` 模块的getLastWindow()方法获取 Window 对象 Window.getLastWindow(context).then((lastWindow) => { this.changeOrientationInternal(lastWindow) }).catch((error) => { console.log("getLastWindow error: " + JSON.stringify(error)) }) }
1
2
3
4
5
6
7
8
9
10完整样例演示
import Window from '@ohos.window' @Entry @Component struct ArkUIClubTest { private portrait: boolean = true build() { Stack() { Button("横竖屏切换") .onClick(() => { this.changeOrientation() }) } .width('100%') .height('100%') } private changeOrientation() { var context = globalThis.context as Context Window.getLastWindow(context).then((lastWindow) => { this.changeOrientationInternal(lastWindow) }).catch((error) => { console.log("getLastWindow error: " + JSON.stringify(error)) }) } private changeOrientationInternal(lastWindow: Window.Window) { if (this.portrait) { // 切换成横屏 lastWindow.setPreferredOrientation(Window.Orientation.LANDSCAPE).then(() => { console.log("setPreferredOrientation success") this.portrait = !this.portrait }).catch((error) => { console.log("setPreferredOrientation failure" + JSON.stringify(error)) }) } else { // 切换成竖屏 lastWindow.setPreferredOrientation(Window.Orientation.PORTRAIT).then(() => { console.log("setPreferredOrientation success") this.portrait = !this.portrait }).catch((error) => { console.log("setPreferredOrientation failure: " + JSON.stringify(error)) }) } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
通过getMainWindow() 方法
通过
WindowStage
的 getMainWindow() 方法获取Window
对象时需要一个WindowStage
对象作为参数,该对象可在MainAbility
的 onWindowStageCreate() 方法中获取,实现步骤如下所示:保存WindowStage对象
import hilog from '@ohos.hilog'; import Ability from '@ohos.application.Ability' import Window from '@ohos.window' export default class MainAbility extends Ability { // 省略部分代码 onWindowStageCreate(windowStage: Window.WindowStage) { // Main window is created, set main page for this ability // 通过globalThis保存windowStage对象 globalThis.windowStage = windowStage windowStage.loadContent('pages/index', (err, data) => {}); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16获取 Window 对象
private changeOrientation() { // 拿到globalThis保存的windowStage var windowStage = globalThis.windowStage as Window.WindowStage windowStage.getMainWindow().then((mainWindow) => { this.changeOrientationInternal(mainWindow) }).catch((error) => { console.log("getMainWindow error: " + JSON.stringify(error)) }) }
1
2
3
4
5
6
7
8
9完整样例演示
import Window from '@ohos.window' @Entry @Component struct ArkUIClubTest { private portrait: boolean = true build() { Stack() { Button("横竖屏切换") .onClick(() => { this.changeOrientation() }) } .width('100%') .height('100%') } private changeOrientation() { var windowStage = globalThis.windowStage as Window.WindowStage windowStage.getMainWindow().then((mainWindow) => { this.changeOrientationInternal(mainWindow) }).catch((error) => { console.log("getMainWindow error: " + JSON.stringify(error)) }) } private changeOrientationInternal(lastWindow: Window.Window) { if (this.portrait) { // 切换成横屏 lastWindow.setPreferredOrientation(Window.Orientation.LANDSCAPE).then(() => { console.log("setPreferredOrientation success") this.portrait = !this.portrait }).catch((error) => { console.log("setPreferredOrientation failure" + JSON.stringify(error)) }) } else { // 切换成竖屏 lastWindow.setPreferredOrientation(Window.Orientation.PORTRAIT).then(() => { console.log("setPreferredOrientation success") this.portrait = !this.portrait }).catch((error) => { console.log("setPreferredOrientation failure: " + JSON.stringify(error)) }) } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
通过getContext()方法
ArkUI 开发框架在 Stage 开发模型中提供在页面里直接获取当前页面的
Context
方法,有了Context
后就可以直接调用@ohos.window
模块的 getLastWindow() 方法获取Window
对象了,实现步骤如下所示:获取 Context 对象
private changeOrientation() { // 获取Context对象 var context = getContext(this) as context.Context }
1
2
3
4获取 Window 对象
private changeOrientation() { var context = getContext(this) as context.Context Window.getLastWindow(context).then((lastWindow) => { this.changeOrientationInternal(lastWindow) }).catch((error) => { console.log("getLastWindow error: " + JSON.stringify(error)) }) }
1
2
3
4
5
6
7
8完整样例演示
import context from '@ohos.application.context'; import Window from '@ohos.window' @Entry @Component struct ArkUIClubTest { private portrait: boolean = true build() { Stack() { Button("横竖屏切换") .onClick(() => { this.changeOrientation() }) } .width('100%') .height('100%') } private changeOrientation() { var context = getContext(this) as context.Context Window.getLastWindow(context).then((lastWindow) => { this.changeOrientationInternal(lastWindow) }).catch((error) => { console.log("getLastWindow error: " + JSON.stringify(error)) }) } private changeOrientationInternal(lastWindow: Window.Window) { if (this.portrait) { // 切换成横屏 lastWindow.setPreferredOrientation(Window.Orientation.LANDSCAPE).then(() => { console.log("setPreferredOrientation success") this.portrait = !this.portrait }).catch((error) => { console.log("setPreferredOrientation failure" + JSON.stringify(error)) }) } else { // 切换成竖屏 lastWindow.setPreferredOrientation(Window.Orientation.PORTRAIT).then(() => { console.log("setPreferredOrientation success") this.portrait = !this.portrait }).catch((error) => { console.log("setPreferredOrientation failure: " + JSON.stringify(error)) }) } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
📢:笔者介绍了以上三种方式在 Stage 模型中进行横竖屏切换的操作,由于笔者手机的 HarmonyOS 版本为 3.0,暂不支持 Stage 模型应用开发,以上三种方式没有经过验证,只是笔者通过查看 API 推理出来的方法,不一定好使……
# 18.4.3:监听横竖屏切换
ArkUI 开发框架在 '@ohos.mediaquery'
模块里提供了监听横竖屏切换的方法,伪代码如下:
// 引入模块
import mediaquery from '@ohos.mediaquery';
// 监听横竖屏切换
private monitorOrientationChanged() {
var listener = mediaquery.matchMediaSync("(orientation: landscape)")
listener.on("change", (result) => {
if (result.matches) {
// 横屏
} else {
// 竖屏
}
})
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 18.4.4:小结
本节简单介绍了在不同开发模型下实现横竖屏的方法供读者参考,由于笔者没法验证在 Stage 模型下的结果,欢迎有设备的小伙伴帮笔者验证一下结果以及给本网站提供更多的开发样例。