在这里插入图片描述

你是不是也在想——“鸿蒙这么火,我能不能学会?”
答案是:当然可以!
这个专栏专为零基础小白设计,不需要编程基础,也不需要懂原理、背术语。我们会用最通俗易懂的语言、最贴近生活的案例,手把手带你从安装开发工具开始,一步步学会开发自己的鸿蒙应用。
不管你是学生、上班族、打算转行,还是单纯对技术感兴趣,只要你愿意花一点时间,就能在这里搞懂鸿蒙开发,并做出属于自己的App!
📌 关注本专栏《零基础学鸿蒙开发》,一起变强!
每一节内容我都会持续更新,配图+代码+解释全都有,欢迎点个关注,不走丢,我是小白酷爱学习,我们一起上路 🚀

前言

在开发 HarmonyOS 应用的全屏视频播放、沉浸式阅读或游戏界面时,经常遇到这样一个需求:把屏幕顶部的系统状态栏“去掉”。

但在实际落地过程中,不少开发者容易混淆沉浸式布局与隐藏系统栏这两个概念。有时代码调了 setWindowLayoutFullScreen(true),却发现状态栏的时间、电池图标依然漂浮在画面上方;有时通过接口把状态栏隐藏了,页面顶部却留下一块死板的空白区域。

本文聚焦这一个常见误区,从 HarmonyOS Window Kit 官方 API 设计出发,厘清两者的本质区别,并提供可复现的 ArkTS 实现方案。

一、核心概念:沉浸式布局 vs 隐藏系统栏

在 Stage 模型中,系统栏(包含顶部状态栏 Status Bar、底部导航条/导航栏 Navigation Bar)的管理涉及两个不同的维度:布局空间 与 组件显隐。

把这两个维度的控制搞混,是引发界面异常的主要原因。

+-------------------------------------------------------------------+
|                        System Status Bar                          |
|  [Time, Battery, Wi-Fi Icons]  <-- Controlled by setSpecific...   |
+-------------------------------------------------------------------+
|                                                                   |
|                         Window Content Area                       |
|                                                                   |
|   - Default: Content rendered inside safe area                    |
|   - Layout Fullscreen: Content extends under Status/Nav Bar       |
|                                                                   |
+-------------------------------------------------------------------+
|                      System Navigation Bar                        |
+-------------------------------------------------------------------+

【建议插图1:沉浸式布局与隐藏系统栏的视觉与布局区域对比示意图】

1. 沉浸式布局(Layout FullScreen)

  • 控制 API:windowClass.setWindowLayoutFullScreen(true) 或组件级 expandSafeArea()
  • 解决的问题:控制窗口的绘制区域是否延伸到系统栏下方。
  • 视觉表现:页面背景可以铺满整个屏幕(延伸到状态栏和导航栏底部),但状态栏上的时间、电量图标依然显示,叠放在应用内容上方。

2. 隐藏系统栏(Hide System Bars)

  • 控制 API:windowClass.setSpecificSystemBarEnabled('status', false)
  • 解决的问题:控制系统状态栏或导航栏等控件本身的视觉可见性(是否绘制时间、电量、通知图标或底栏)。
  • 视觉表现:系统状态栏中的文字和图标彻底消失,屏幕顶部不再展示系统状态信息。

误区归纳

典型误区:“我只想做全屏背景,直接调用隐藏状态栏就好了” 或者 “我调用了 setWindowLayoutFullScreen(true),状态栏怎么没消失?”

  • 如果只隐藏状态栏而没有开启沉浸式布局,窗口内容可能依然保留在原安全区域内,导致顶部留白。
  • 如果只开启沉浸式布局而没有隐藏状态栏,应用内容会延伸到顶部,但状态栏图标依然会遮挡应用顶部的 UI 元素(例如返回按钮或标题)。

二、官方 API 规范与使用条件

在 HarmonyOS 官方 API 中,系统栏的管理推荐使用 @kit.ArkUI 中的 window 模块。

关键接口说明

  1. setWindowLayoutFullScreen

    • 作用:设置主窗口是否为沉浸式布局。
    • 参数:isLayoutFullScreen: boolean
    • 返回值:Promise<void>
  2. setSpecificSystemBarEnabled

    • 作用:控制指定系统栏(状态栏 'status' 或导航指示条 'navigationIndicator')的显示与隐藏。

    • 参数:

      • name: 'status' | 'navigationIndicator'
      • enable: boolean
      • enableAnimation: boolean(可选,控制控制显隐过程中的过渡动画)
    • 返回值:Promise<void>

注意:早期的 setWindowSystemBarEnable 接口在较新版本中已被更细粒度的 setSpecificSystemBarEnabled 替代,建议根据开发环境选择规范的 API。

三、最小实践场景

下面构造一个最小可复现示例,演示如何正确组合“沉浸式布局”与“隐藏状态栏”,并在页面切出时恢复默认系统状态。

1. 获取窗口实例与页面状态控制

在 ArkTS 页面中,需要先通过上下文(Context)获取当前 UIAbility 的主窗口实例。

【建议插图2:应用在“未开启沉浸式”、“仅沉浸式”、“沉浸式+隐藏状态栏”三种模式下的真机运行效果对比】

2. 核心代码实现

以下为组件内控制系统栏状态的代码实现:

import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';

@Entry
@Component
struct SystemBarDemoPage {
  @State isFullScreen: boolean = false;
  @State isStatusBarVisible: boolean = true;
  private windowClass: window.Window | null = null;

  aboutToAppear() {
    // 获取当前组件的 Context 并加载窗口实例
    let context = getContext(this) as common.UIAbilityContext;
    window.getLastWindow(context, (err: BusinessError, data: window.Window) => {
      if (err.code) {
        console.error(`Failed to obtain the top window. Cause: ${JSON.stringify(err)}`);
        return;
      }
      this.windowClass = data;
    });
  }

  aboutToDisappear() {
    // 页面销毁时重置系统状态,避免影响其他页面
    this.resetSystemBar();
  }

  /**
   * 切换沉浸式布局状态
   */
  private toggleLayoutFullScreen(enable: boolean) {
    if (!this.windowClass) return;
    
    this.windowClass.setWindowLayoutFullScreen(enable)
      .then(() => {
        this.isFullScreen = enable;
        console.info(`Succeeded in setting window layout full screen: ${enable}`);
      })
      .catch((err: BusinessError) => {
        console.error(`Failed to set window layout full screen. Cause: ${JSON.stringify(err)}`);
      });
  }

  /**
   * 切换状态栏显示/隐藏
   */
  private toggleStatusBar(enable: boolean) {
    if (!this.windowClass) return;

    // 控制顶部状态栏显隐,可选带过渡动画
    this.windowClass.setSpecificSystemBarEnabled('status', enable, true)
      .then(() => {
        this.isStatusBarVisible = enable;
        console.info(`Succeeded in setting status bar enabled: ${enable}`);
      })
      .catch((err: BusinessError) => {
        console.error(`Failed to set status bar enabled. Cause: ${JSON.stringify(err)}`);
      });
  }

  /**
   * 恢复系统状态栏默认显示
   */
  private resetSystemBar() {
    if (!this.windowClass) return;
    
    this.windowClass.setWindowLayoutFullScreen(false);
    this.windowClass.setSpecificSystemBarEnabled('status', true);
  }

  build() {
    Column() {
      Text("System Bar Practice")
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 40, bottom: 20 })

      Column({ space: 12 }) {
        Button(this.isFullScreen ? "Disable Immersive Layout" : "Enable Immersive Layout")
          .width('80%')
          .onClick(() => {
            this.toggleLayoutFullScreen(!this.isFullScreen);
          })

        Button(this.isStatusBarVisible ? "Hide Status Bar" : "Show Status Bar")
          .width('80%')
          .onClick(() => {
            this.toggleStatusBar(!this.isStatusBarVisible);
          })

        Button("Reset Window Settings")
          .width('80%')
          .backgroundColor(Color.Gray)
          .onClick(() => {
            this.resetSystemBar();
            this.isFullScreen = false;
            this.isStatusBarVisible = true;
          })
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F1F3F5')
  }
}

四、关键实现分析与注意事项

1. 生命周期管理:避免全局状态污染

窗口的系统栏设置是应用窗口级别的,而不是页面级别的。

如果在 PageA 中调用了 setSpecificSystemBarEnabled('status', false) 隐藏了状态栏,但在跳转到 PageB 时没有恢复,PageB 的顶部状态栏依然会保持隐藏状态。

建议做法:

  • 在需要沉浸式/全屏的页面的 onPageShow() 或 aboutToAppear() 中配置窗口状态。
  • 在页面退出(onPageHide() 或 aboutToDisappear())时,明确将系统栏状态恢复为默认。

2. 安全区域(Safe Area)适配

当开启沉浸式布局(setWindowLayoutFullScreen(true))但未隐藏状态栏时,页面的顶部组件会被状态栏覆盖。

如果顶部有交互控件(如返回按钮、搜索框),需要配合 ArkUI 组件的避让策略:

  • 可以给顶部容器设置避让边距,获取状态栏高度:windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM)。
  • 或使用组件属性 .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP]) 控制特定组件扩展至不安全区域。

【建议插图3:窗口避让区域(AvoidArea)计算示意图】

五、实际开发排查顺序

在处理系统栏相关问题时,可按以下流程进行检查:

+-------------------------------------------------------------+
| Check 1: Is Window instance retrieved successfully?         |
+-------------------------------------------------------------+
                              |
                              v
+-------------------------------------------------------------+
| Check 2: Are you calling setWindowLayoutFullScreen or       |
| setSpecificSystemBarEnabled? Confirm intended visual outcome|
+-------------------------------------------------------------+
                              |
                              v
+-------------------------------------------------------------+
| Check 3: Are lifecycle reset mechanisms implemented on      |
| page transition / destroy?                                  |
+-------------------------------------------------------------+
                              |
                              v
+-------------------------------------------------------------+
| Check 4: Check expandSafeArea settings on root components    |
+-------------------------------------------------------------+
  1. 检查窗口实例:确认是否在有效的上下文生命周期中成功通过 window.getLastWindow() 获取了 Window 对象。

  2. 区分布局与显隐需求:

    • 想要背景延伸到状态栏下方,内容不隐藏状态栏:使用 setWindowLayoutFullScreen(true)。
    • 想要彻底不见顶部状态栏:调用 setSpecificSystemBarEnabled('status', false)。
  3. 检查生命周期恢复:跨页面跳转后,检查前一个页面是否在隐藏/销毁生命周期中还原了窗口参数。

  4. 检查安全区域:确认根组件是否误用了 .expandSafeArea() 导致布局穿透错位。

六、总结

开发全屏与沉浸式体验时,务必分清“布局延伸”与“系统栏视觉显隐”两个维度的 API:

  1. setWindowLayoutFullScreen 决定窗口内容画到哪里(是否穿透安全区域)。
  2. setSpecificSystemBarEnabled 决定状态栏本身的图标和内容是否绘制。
  3. 窗口设置是窗口全局生效的,必须在页面生命周期中做好状态复原。

参考资料

  1. 《Window Kit 开发指南 - 管理系统栏》
    华为开发者联盟
    链接:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/application-window-stage

  2. 《ArkUI API 参考 - Window 模块》
    华为开发者联盟
    链接:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-window

❤️ 如果本文帮到了你…

  • 请点个赞,让我知道你还在坚持阅读技术长文!
  • 请收藏本文,因为你以后一定还会用上!
  • 如果你在学习过程中遇到bug,请留言,我帮你踩坑!
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐