# 18.4:横竖屏切换

我们在应用开发的过程中,可能会遇见横竖屏切换的场景,比如视频类应用在播放视频的时候有切换横屏的场景。本节笔者简单介绍一下横竖屏切换在 FA 模型和 State 模型下的两种实现方式。

# 18.4.1:FA模型实现

在 FA 模型下实现横竖屏比较简单,直接使用 @ohos.ability.featureAbilitygetContext() 方法获取一个 Conetxt,然后调用该 ContextsetDisplayOrientation() 方法即可,示例代码如下:

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))
      })
    }
  }
}
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

样例运行结果如下图所示:

18_4_1_1

# 18.4.2:Stage模型实现

OpenHarmony 在 API 9 上提供了不同于 FA 模型的 Stage 开发模型,Stage 模型的设计基于 为复杂应用而设计支持多设备和多窗口形态平衡应用能力系统管控成本 为出发点而设计出来的。

在 Stage 模型下,可以通过 Window 对象的 setPreferredOrientation() 方法实现横竖屏切换,笔者梳理了以下三种方式:

  • 通过getLastWindow() 方法

    通过 @ohos.window 模块的 getLastWindow() 方法获取 Window 对象时需要一个 Context 对象作为参数,该对象可在 MainAbilityonCreate() 方法中获取,实现步骤如下所示:

    • 保存 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() 方法

    通过 WindowStagegetMainWindow() 方法获取 Window 对象时需要一个 WindowStage 对象作为参数,该对象可在 MainAbilityonWindowStageCreate() 方法中获取,实现步骤如下所示:

    • 保存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 {
      // 竖屏
    }
  })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 18.4.4:小结

本节简单介绍了在不同开发模型下实现横竖屏的方法供读者参考,由于笔者没法验证在 Stage 模型下的结果,欢迎有设备的小伙伴帮笔者验证一下结果以及给本网站提供更多的开发样例。

(adsbygoogle = window.adsbygoogle || []).push({});
请作者喝杯咖啡

津公网安备 12011402001367号

津ICP备2020008934号-2