HarmonyNEXT:沉浸式效果实现

2025-06-25 21:39:50
109次阅读
0个评论

本文标签:HarmonyOS/ArkUI

本文支持的API>=18

之所以要实现沉浸式效果,最主要的目的就是提升用户体验,使状态栏的效果和页面的主题保持一致,增加视觉上的体验,试想一下,如果没有沉浸式,在视觉上会显得很是突兀,如下图所示,就可以看到,页面是红色,而状态栏是白色,显得很是不搭配。

image.png

正因为有了沉浸式,才让开发的应用在视觉上显得是那么的清新,可以说,目前市面上的很多应用,都已经适配了沉浸式,我们可以随便打开一个应用,比如微信,比如支付宝,比如各个购物软件,其顶部的透明化状态栏可以说是随处可见。

image.png

我们需要知道的是,沉浸式效果,主要是指通过隐藏或透明化状态栏和导航栏,使应用内容扩展至屏幕边缘,也就是扩展到顶部的状态栏区域和底部的导航栏区域,主要的目的,上面也说了,就是为了提升用户体验。

鸿蒙开发当中,实现一个沉浸式,可以说是十分的简单,目前有两种实现方式,一种是页面内独立设置,也就是安全区域避让,另一种是全局配置。

安全区域避让

安全区域避让,主要是通过在页面内给组件设置expandSafeArea属性来实现沉浸式效果,大家一定要知道,所谓的安全区域就是指页面的显示区域,也就是状态栏、导航栏区域之外的区域。

expandSafeArea

点击expandSafeArea属性,我们可以进入到源码中,可以看到,expandSafeArea目前接收了两个参数,第一个参数types,它的类型是Array ,由问号来标识,可以知道,非必传参数,它的作用,主要是配置扩展安全区域的类型,当没有添加metadata配置项时,页面事不避让挖孔的, CUTOUT类型不生效;第二个参数edges,它的类型是Array ,也是非必传参数,主要作用是配置扩展安全区域的方向。

 expandSafeArea(types?: Array<SafeAreaType>, edges?: Array<SafeAreaEdge>): T;

SafeAreaType

扩展安全区域的枚举类型,目前有以下三种。

名称 描述
SYSTEM 系统默认非安全区域,包括状态栏、导航栏。
CUTOUT 设备的非安全区域,例如刘海屏或挖孔屏区域。
KEYBOARD 软键盘区域。

SafeAreaEdge

扩展安全区域的方向,目前有以下四种。

名称 描述
TOP 上方区域。
BOTTOM 下方区域。
START 前部区域。
END 尾部区域。

主要实现

实现起来很是简单,代码如下所示:

 Column() {

    }.width("100%")
    .height("100%")
    .backgroundColor(Color.Red)
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])

我们看下实际的运行效果,可以看到,导航栏和状态栏均已实现了沉浸式。

image.png

如果你要修改状态栏的图标颜色,可以结合windows来实现。

在独立页面中,除了以上的安全区域避让,我们还可以直接获取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));
      });
    })
  }

全局设置

在实际的开发中,如果我们的整个项目都是沉浸式效果,那么我们完全可以使用全局配置,这样就会应用于所有的页面,其实现呢,主要是通过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()

当我们设置了以上的代码后,如果运行项目,会发现,我们的内容页面会扩展到非安全区域。

image.png

为了解决以上的问题,在安全区域的内容,需要避开导航条和状态栏。这种情况下,我们就需要把整体的UI视图,在状态栏之下,可以先获取状态栏的高度,然后进行设置即可:

Column() {
        Text("我是标题")
          .width("100%")
          .height(40)
          .textAlign(TextAlign.Center)
          .fontColor(Color.White)
      }.width("100%")
      .padding({ top: this.navHeight })
      .backgroundColor(Color.Red)

可以看到,我们的标题已经正常展示了。

image.png

获取状态栏和导航栏高度的代码如下,前提需要获取window,可以通过window.getLastWindow来获取。

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

注意事项

如果你想给单一的页面进行设置沉浸式,这里推荐使用expandSafeArea来避让安全区域,因为expandSafeArea属性是给组件设置的,不会影响到别的页面,只对当前的页面有效果,在使用expandSafeArea属性时,如果根组件是滚动组件,是不生效的,这一点需要注意;如果是整个项目都需要进行沉浸式,可以使用全局配置,还有,在内容区域中,需要控制好组件的位置,避免状态栏或导航栏覆盖内容区域。

收藏00

登录 后评论。没有帐号? 注册 一个。