沉浸式怎么设置
头像 wuwuwu 2026-06-01 15:41:06    发布
3 浏览 0 点赞 0 收藏

一、先搞懂两个核心概念(必须懂)


1. 沉浸式(全屏布局)

win.setWindowLayoutFullScreen(true)
  • 让你的页面布局延伸到状态栏、底部导航栏下面
  • 系统栏(状态栏 / 导航栏)悬浮在页面上方
  • 不设置的话,页面会自动避开系统栏,不会沉浸式

2. 安全区(AvoidArea)

系统会占用屏幕顶部、底部的区域,这些地方不能放按钮、文字,否则会被挡住。


我们需要:


  1. 获取这些区域的高度
  2. 存到全局
  3. 页面用 padding 把内容 “让开” 这些高度


二、完整项目结构(对照你自己的)

src/
├── commons/
│   ├── constants/
│   │   └── index.ets       # 全局常量key
│   └── utils/
│       ├── HMLogger.ets    # 日志工具
│       ├── HMScreenManager.ets  # 沉浸式工具
│       └── index.ets       # 统一导出
├── EntryAbility.ets        # 入口初始化
└── pages/
    └── Index.ets           # 测试页面


三、第一步:定义全局常量(必须)

export class GlobalVariable {
  // 安全区高度存储的 key
  static readonly SAFE_TOP_HEIGHT = 'safeTopHeight'
  static readonly SAFE_BOTTOM_HEIGHT = 'safeBottomHeight'
}


四、第二步:封装沉浸式工具(核心)

import { window, px2vp } from '@kit.ArkUI'
import { Context } from '@kit.AbilityKit'
import { GlobalVariable } from '../constants'
import { hmLogger } from './HMLogger'

class HMScreenManager {
  // 保存上下文(必须要有才能获取窗口)
  private mContext: Context | null = null

  /**
   * 初始化上下文
   * 在 EntryAbility 的 onWindowStageCreate 中调用
   */
  init(context: Context): this {
    this.mContext = context
    return this
  }

  /**
   * 开启沉浸式 + 自动获取并设置安全区高度
   */
  async enableImmersive(): Promise<void> {
    try {
      if (!this.mContext) {
        hmLogger.error('上下文为空,无法开启沉浸式')
        return
      }

      // 1. 获取当前应用窗口
      const currentWindow = await window.getLastWindow(this.mContext)

      // 2. 开启沉浸式布局(关键)
      await currentWindow.setWindowLayoutFullScreen(true)

      // ==============================================
      // 3. 获取 状态栏高度(顶部安全区)
      // ==============================================
      const systemAvoidArea = currentWindow.getWindowAvoidArea(
        window.AvoidAreaType.TYPE_SYSTEM
      )
      // 像素转虚拟像素(ArkUI 开发必须转)
      const statusBarHeight = px2vp(systemAvoidArea.topRect.height)

      // ==============================================
      // 4. 获取 底部导航栏高度(底部安全区)
      // ==============================================
      const navAvoidArea = currentWindow.getWindowAvoidArea(
        window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR
      )
      const navBarHeight = px2vp(navAvoidArea.bottomRect.height)

      // ==============================================
      // 5. 设置安全区高度到全局 AppStorage
      // ==============================================
      AppStorage.setOrCreate(GlobalVariable.SAFE_TOP_HEIGHT, statusBarHeight)
      AppStorage.setOrCreate(GlobalVariable.SAFE_BOTTOM_HEIGHT, navBarHeight)

      hmLogger.info(`沉浸式开启成功
        状态栏高度:${statusBarHeight}
        导航栏高度:${navBarHeight}
      `)

    } catch (error) {
      hmLogger.error('开启沉浸式失败:', error)
    }
  }

  /**
   * 关闭沉浸式 + 重置安全区高度为 0
   */
  async disableImmersive(): Promise<void> {
    try {
      if (!this.mContext) return

      const currentWindow = await window.getLastWindow(this.mContext)

      // 关闭沉浸式
      await currentWindow.setWindowLayoutFullScreen(false)

      // ==============================================
      // 关闭沉浸式后,安全区高度要重置为 0
      // ==============================================
      AppStorage.setOrCreate(GlobalVariable.SAFE_TOP_HEIGHT, 0)
      AppStorage.setOrCreate(GlobalVariable.SAFE_BOTTOM_HEIGHT, 0)

      hmLogger.info('沉浸式已关闭,安全区高度重置为0')

    } catch (error) {
      hmLogger.error('关闭沉浸式失败:', error)
    }
  }
}

// 单例模式,全局唯一
export const hmScreenManager = new HMScreenManager()




五、第三步:工具统一导出(方便页面引用)

export * from './HMLogger'
export * from './HMScreenManager'


六、第四步:在入口初始化(非常关键)

import { AbilityConstant, UIAbility, WindowStage } from '@kit.AbilityKit'
import { window } from '@kit.ArkUI'
import { hmScreenManager } from './commons/utils'

export default class EntryAbility extends UIAbility {

  onWindowStageCreate(windowStage: WindowStage): void {
    // 初始化上下文,并直接开启沉浸式
    hmScreenManager.init(this.context).enableImmersive()

    windowStage.loadContent('pages/Index', (err) => {
      if (err) {
        return
      }
    })
  }
}




七、第五步:页面如何使用安全区高度(重点)

import { GlobalVariable } from '../commons/constants'

@Entry
@Component
struct Index {
  // 从全局 AppStorage 接收安全区高度
  @StorageProp(GlobalVariable.SAFE_TOP_HEIGHT) safeTop: number = 0;
  @StorageProp(GlobalVariable.SAFE_BOTTOM_HEIGHT) safeBottom: number = 0;

  build() {
    Column() {
      Text("我是顶部,不会被状态栏挡住")
        .fontSize(24)
        .fontColor(Color.White)

      Blank()

      Text("我是底部,不会被导航栏挡住")
        .fontSize(24)
        .fontColor(Color.White)

      // 测试开关沉浸式按钮
      Button("关闭沉浸式")
        .onClick(() => {
          hmScreenManager.disableImmersive()
        })
        .margin(10)

      Button("开启沉浸式")
        .onClick(() => {
          hmScreenManager.enableImmersive()
        })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#ff2d8cf0')
    // ==============================================
    // 核心:设置 padding 避开安全区
    // ==============================================
    .padding({
      top: this.safeTop,
      bottom: this.safeBottom
    })
  }
}




八、重点总结:安全区高度到底怎么 “设置”?

很多人卡在这里,我用最简单的话讲:


1. 获取高度

const topArea = win.getWindowAvoidArea(TYPE_SYSTEM)
const statusBarHeight = px2vp(topArea.topRect.height)

2. 存入全局(设置高度)

AppStorage.setOrCreate('safeTopHeight', statusBarHeight)

这一步就叫:设置安全区高度

3. 页面使用(应用高度)

typescript

运行


@StorageProp('safeTopHeight') top
.padding({ top: top })




九、完整开关沉浸式效果


  • 开启:页面全屏,内容自动避开状态栏、导航栏
  • 关闭:恢复正常,安全区高度变为 0
  • 所有高度自动同步,不需要页面手动改


十、你可能遇到的问题


  1. 报错:context 为 null → 必须在 EntryAbility.onWindowStageCreate 初始化
  2. 内容被状态栏挡住 → 没加 .padding({ top: this.safeTop })
  3. 高度不对 → 必须用 px2vp 转换
  4. 切换页面失效 → 因为是全局单例 + AppStorage,所有页面自动生效
©本站发布的所有内容,包括但不限于文字、图片、音频、视频、图表、标志、标识、广告、商标、商号、域名、软件、程序等,除特别标明外,均来源于网络或用户投稿,版权归原作者或原出处所有。我们致力于保护原作者版权,若涉及版权问题,请及时联系我们进行处理。
分类
HarmonyOS
头像

wuwuwu

我还没有写个人简介......

5

帖子

0

提问

0

粉丝

关注
最新发布

沉浸式怎么设置

2026-06-01 15:41:06    发布

鸿蒙系统是否会推出一个自己的框架

2026-05-28 11:08:46    发布
热门推荐
地址:北京市朝阳区北三环东路三元桥曙光西里甲1号第三置业A座1508室 商务内容合作QQ:2291221 电话:13391790444或(010)62178877
版权所有:电脑商情信息服务集团 北京赢邦策略咨询有限责任公司
声明:本媒体部分图片、文章来源于网络,版权归原作者所有,我司致力于保护作者版权,如有侵权,请与我司联系删除

京ICP备:2022009079号-2

京公网安备:11010502051901号

ICP证:京B2-20230255