# 18.3:沉浸式设置

HarmonyOS 3.0 已经支持使用 ArkUI 开发框架开发 APP 了,使用最新版 DevEco Studio 创建一个 HarmonyOS 工程,编辑 index.ets 页面,代码如下:

@Entry @Component struct Index {
  build() {
    Column() {
      Text("OpenHarmony")
        .fontSize(35)
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Pink) // 设置页面背景色为 Pink
  }
}
1
2
3
4
5
6
7
8
9
10
11

默认情况下页面启动后的布局样式是带有一个黑色背景的标题栏,如下所示:

18_3_1

页面布局从上往下看,蓝色框表示的系统状态栏,绿色框表示的是 APP 的标题栏,红色框表示的 APP 页面,紫色框表示的导航栏,如果想把页面做成 Android 或 iOS 那样的沉浸式样式,该如何实现呢?本节笔者就简单介绍一下在 HarmonyOS 上实现沉浸式的做法。

# 18.3.1:隐藏标题栏

要实现沉浸式体验,首先要把标题栏隐藏,隐藏标题栏直接设置 Ability 的 Theme 即可,实现方式是在 config.json 配置文件里的 module 属性中添 metaData 配置,代码如下:

{
  "app": {
    // ...
  },
  "module": {
    "package": "com.example.entry",
    "metaData": { // 添加主题配置,所有 Ability 均生效
      "customizeData": [
        {
          "name": "hwc-theme",
          "value": "androidhwext:style/Theme.Emui.Light.NoTitleBar" // 隐藏标题栏
        }
      ]
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

通过给 module 添加 metaData 配置,表示对 APP 内所有的 Ability 的主题均设置为白色背景无标题栏的样式,应用启动后截图如下所示:

18_3_1_1

📢:也可以在 module 下的 abilities 中添加 metaData 属性,表示只对当前的 Ability 生效, HarmonyOS 提供的官方主题主要有以下几种,读者可自行体验个主题的差异。

主题 描述
androidhwext:style/Theme.Emui.NoTitleBar 无标题
androidhwext:style/Theme.Emui.NoDisplay 无界面
androidhwext:style/Theme.Emui.Light.NoTitleBar.Fullscreen 全屏无状态栏
androidhwext:style/Theme.Emui.Dialog 将页面显示为对话框模式
androidhwext:style/Theme.Emui.NoTitleBar 不显示应用程序标题栏
androidhwext:style/Theme.Emui.NoTitleBar.Fullscreen 不显示应用程序标题栏,并全屏
androidhwext:style/Theme.Emui.Light 背景为白色
androidhwext:style/Theme.Emui.Light.NoTitleBar 白色背景并无标题栏
androidhwext:style/Theme.Emui.Light.NoTitleBar.Fullscreen 白色背景,无标题栏,全屏
androidhwext:style/Theme.Emui.Black 背景黑色
androidhwext:style/Theme.Emui.Black.NoTitleBar 黑色背景并无标题栏
androidhwext:style/Theme.Emui.Black.NoTitleBar.Fullscreen 黑色背景,无标题栏,全屏
androidhwext:style/Theme.Emui.Wallpaper 用系统桌面为应用程序背景
androidhwext:style/Theme.Emui.Wallpaper.NoTitleBar 用系统桌面为应用程序背景,且无标题栏
androidhwext:style/Theme.Emui.Wallpaper.NoTitleBar.Fullscreen 用系统桌面为应用程序背景,无标题栏,全屏
androidhwext:style/Emui.Translucent 透明背景
androidhwext:style/Theme.Emui.Translucent.NoTitleBar 透明背景并无标题
androidhwext:style/Theme.Emui.Translucent.NoTitleBar.Fullscreen 透明背景并无标题,全屏
androidhwext:style/Theme.Emui.Panel 面板风格显示
androidhwext:style/Theme.Emui.Light.Panel 平板风格显示

# 18.3.2:隐藏导航栏

ArkUI 开发框架在 @ohos.window 模块中提供了设置隐藏状态栏和导航栏的方法 setSystemBarEnable(names: Array<'status' | 'navigation'>),该方法参数 names 是一个数组,只支持 statusnavigation。设置隐藏导航栏只需要设置 names 参数只包含 status 即可,如果都不显示只设置 names[] 即可。代码如下:

import window from '@ohos.window';

export default {
  onCreate() {
    console.info('Application onCreate')
    window.getTopWindow((error, window) => {
      if (window) 
        window.setSystemBarEnable(["status"], (error) => { // 设置只显示状态栏
          if (error) {
            console.log("error: " + JSON.stringify(error))
          }
        })
    })
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

项目运行结果如下图所示:

18_3_2_1

如上图所示,页面的状态栏是白色背景,此时还需要设置状态栏颜色才能完美体验沉浸式。

# 18.3.3:设置状态栏颜色

ArkUI 开发框架在 @ohos.window 库中提供了设置状态栏颜色的方法 setSystemBarProperties() 和设置布局充满全屏的方法 setLayoutFullScreen(),如果实现沉浸式,可以设置状态栏颜色为透明,然后让页面布局充满全屏,代码如下:

import window from '@ohos.window';

export default {
  onCreate() {
    console.info('Application onCreate')
    window.getTopWindow((error, window) => {
      if (window)
        window.setSystemBarEnable(["status"], (error) => {
          if (error) {
            console.log("error: " + JSON.stringify(error))
          }
        })
        window.setSystemBarProperties({
          statusBarColor: "#00000000"     // 设置状态栏背景色为透明
        })
        window.setLayoutFullScreen(true, (error) => { // 设置布局充满全屏
          if (error) {
            console.log("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

样例运行结果如下所示:

18_3_2_1

从运行效果看,即将达到沉浸式效果了,但是 OpenHarmony 文字却显示在了状态栏下边,因为 setLayoutFullScreen() 方法设置全屏布局会导致状态栏遮挡布局内容,为了解决状态栏遮挡的问题,可以设置一下页面根组件的 paddingTop 值为状态栏的高度即可。

# 18.3.4:获取状态栏高度

获取状态栏高度,可以利用 @ohos.window 库中提供的 getAvoidArea() 方法,代码如下:

private getStatusBarHeight() {
  window.getTopWindow((error, topWindow) => {
    if (topWindow) {
      topWindow.getAvoidArea(window.AvoidAreaType.TYPE_SYSTEM, (error, data) => {
        if (data) {
          console.log("left: " + JSON.stringify(data.leftRect))
          console.log("top: " + JSON.stringify(data.topRect))
          console.log("right: " + JSON.stringify(data.rightRect))
          console.log("bottom: " + JSON.stringify(data.bottomRect))
          this.statusBarHeight = px2vp(data.topRect.height)
          console.log("statusBarHeight: " + this.statusBarHeight)
        }
      })
    }
  })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

获取到状态栏高度后,就可以设置页面的根组件的 paddingTop 值了。

# 18.3.5:完整样例

import window from '@ohos.window';
import router from '@ohos.router';

@Entry @Component struct Index {

  @State statusBarHeight: number = 0;

  build() {
    Column() {
      Text("OpenHarmony")
        .fontSize(35)

      Button("打开第二页")
        .onClick(() => {
          router.push({
            url: "pages/second"
          })
        })
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Pink)
    .padding({top: this.statusBarHeight}) // paddingTop 值
  }

  aboutToAppear() {
    if (globalThis.statusBarHeight == undefined) {
      this.getStatusBarHeight()
    } else {
      this.statusBarHeight = globalThis.statusBarHeight
    }
  }

  // 获取状态栏的高度
  private getStatusBarHeight() {
    window.getTopWindow((error, topWindow) => {
      if (topWindow) {
        topWindow.getAvoidArea(window.AvoidAreaType.TYPE_SYSTEM, (error, data) => {
          if (data) {
            console.log("left: " + JSON.stringify(data.leftRect))
            console.log("top: " + JSON.stringify(data.topRect))
            console.log("right: " + JSON.stringify(data.rightRect))
            console.log("bottom: " + JSON.stringify(data.bottomRect))
            this.statusBarHeight = px2vp(data.topRect.height)
            globalThis.statusBarHeight = this.statusBarHeight
            console.log("statusBarHeight: " + px2vp(this.statusBarHeight))
          }
        })
      }
    })
  }
}
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
48
49
50
51
52

第二个页面逻辑和首页是一致的,笔者就不再贴出来了,样例运行结果如下图所示:

18_3_2_1

# 18.3.6:小结

以上就是笔者讲解的沉浸式状态的实现供读者参考,也非常欢迎读者给本网站提供更多的开发样例。更多其他沉浸式设置读者可参考官网 (opens new window)。另外在正式开发过程中,读者可以自己定义一个通用的根组件,避免在每一个页面都要处理 paddingTop 的问题。

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

津公网安备 12011402001367号

津ICP备2020008934号-2