#我的鸿蒙开发手记# HarmonyOS开发之如何实现沉浸式效果 原创 精华
本文基于HarmonyOSApi14。
沉浸式,在实际的开发中,可以说是无处不在,我们可以随便打开一个应用,比如京东淘宝,再比如支付宝微信,其顶部的透明化状态栏可以说是随处可见。

所谓的沉浸式效果主要指通过隐藏或透明化状态栏和导航栏,使应用内容扩展至屏幕边缘,主要用于提升用户体验,如果没有沉浸式,在UI视觉上就会有差异感,体验感是非常的不好,如下的效果,当你不是沉浸式时,就会和顶部的状态栏有明显的差异。

那么,在鸿蒙当中如何来实现一个沉浸式效果呢,目前有多种实现方式可以供我们选择。
全局统一设置
如果我们想针对整个应用都设置沉浸式,我们就可以使用全局统一设置,这样,我们所有的子页面都会进行沉浸式展示,主要是通过window中setWindowLayoutFullScreen方法来设置。
我们可以在主入口的EntryAbility里进行设置:
onWindowStageCreate(windowStage: window.WindowStage): void {
    let windowClass: window.Window = windowStage.getMainWindowSync()
    windowClass.setWindowLayoutFullScreen(true).then(() => {
      console.info('Succeeded in setting the window layout to full-screen mode.');
    }).catch((err: BusinessError) => {
      console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err));
    });
}当然你也可以使用Promise异步获取的方式拿到window,代码如下:
  let window=await windowStage.getMainWindow()以上的代码设置之后需要注意,安全区域的内容,需要避开导航条和状态栏,否则就会被状态栏和导航栏覆盖。

以上的效果可以看到,再设置沉浸式之后,由于没有避让,我们的UI视图直接被上移了,这种情况下,我们就需要把整体的UI视图,在状态栏之下,可以先获取状态栏的高度,然后进行设置即可:
Column() {
        Text("我是测试标题")
          .width("100%")
          .height(40)
          .textAlign(TextAlign.Center)
          .fontColor(Color.White)
      }.width("100%")
      .padding({ top: this.navHeight })
      .backgroundColor(Color.Pink)可以看到,我们的标题已经正常展示了。

获取状态栏和导航栏高度的代码如下:
let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR;
let avoidArea = windowClass.getWindowAvoidArea(type);
let bottomRectHeight = avoidArea.bottomRect.height; //获取导航栏高度
let type = window.AvoidAreaType.TYPE_SYSTEM; 
let avoidArea = win.getWindowAvoidArea(type);
let topRectHeight = avoidArea.topRect.height; // 获取状态栏区域高度有一点需要说的是,如果你的沉浸式是纯颜色的,其实,我们可以直接设置状态栏的颜色即可,其他的代码都不需要修改。
let windowClass: window.Window = windowStage.getMainWindowSync()
    let SystemBarProperties: window.SystemBarProperties = {
      statusBarColor: '#FFC0CB',
      statusBarContentColor: "#ffffff",
    };
    try {
      windowClass.setWindowSystemBarProperties(SystemBarProperties).then(() => {
        console.info('Succeeded in setting the system bar properties.');
      }).catch((err: BusinessError) => {
        console.error(`Failed to set the system bar properties. Cause code: ${err.code}, message: ${err.message}`);
      });
    } catch (exception) {
      console.error(`Failed to set the system bar properties. Cause code: ${exception.code}, message: ${exception.message}`);
    }单页面设置
单页面的话,我们可以直接获取getLastWindow,然后设置。
aboutToAppear(): void {
    window.getLastWindow(getContext(), (_, win) => {
      win.setWindowLayoutFullScreen(true).then(() => {
        console.info('Succeeded in setting the window layout to full-screen mode.');
      }).catch((err: BusinessError) => {
        console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err));
      });
    })
  }除了以上的方式之外,单页面更多的是通过安全区域来实现沉浸式,所谓的安全区域就是指页面的显示区域,也就是状态栏、导航栏区域之外的区域。
如何让安全区域,延伸到状态栏、导航栏,达到沉浸式的效果,其实在鸿蒙中给我们提供expandSafeArea,通过它我们就可以设置到任意的组件上。
Column() {
    }.height("100%")
    .width("100%")
    .backgroundColor(Color.Gray)
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])我们看下实际的运行效果,可以看到,导航栏和状态栏均已实现了沉浸式。

分析expandSafeArea
通过源码,我们可以看到,expandSafeArea接收了两个参数,第一个参数types,类型是Array <SafeAreaType>,通过问号,我们可以知道,这个不是必须得,主要配置扩展安全区域的类型,当未添加metadata配置项时,页面不避让挖孔, CUTOUT类型不生效;第二个参数edges,类型是Array <SafeAreaEdge>,也是不是必须的,配置扩展安全区域的方向。
 expandSafeArea(types?: Array<SafeAreaType>, edges?: Array<SafeAreaEdge>): T;SafeAreaType
扩展安全区域的枚举类型
名称  | 描述  | 
SYSTEM  | 系统默认非安全区域,包括状态栏、导航栏。  | 
CUTOUT  | 设备的非安全区域,例如刘海屏或挖孔屏区域。  | 
KEYBOARD  | 软键盘区域。  | 
SafeAreaEdge
扩展安全区域的方向
名称  | 描述  | 
TOP  | 上方区域。  | 
BOTTOM  | 下方区域。  | 
START  | 前部区域。  | 
END  | 尾部区域。  | 
使用须知
在使用expandSafeArea属性时,有几点需要注意,第一个就是,在可滚动的容器中使用是没有效果的,比如List组件,Scroll组件等等;第二个就是,expandSafeArea属性是给组件设置的,不会影响到别的页面,只对当前的页面有效果,所以,如果是整个项目都是沉浸式,建议选择应用窗口管理进行实现,第三个就是使用到了expandSafeArea属性后,它会延伸至非安全区域,也就是扩展到导航栏和状态栏,在内容区域中,需要控制好组件的位置,避免状态栏或导航栏覆盖内容区域。




















