Appearance
沉浸式状态栏
实现沉浸式状态栏的核心是 window API 和 AppStorage 的系统安全区域。
1. 沉浸式状态栏的概念
传统状态栏 沉浸式状态栏
┌────────────────┐ ┌────────────────┐
│ 状态栏(系统) │ │ (无状态栏) │
├────────────────┤ │ │
│ │ │ │
│ 内容区域 │ │ 内容区域 │
│ │ │ 延伸到顶部 │
│ │ │ │
└────────────────┘ └────────────────┘2. 全屏布局实现
2.1 基本方法
typescript
import { window } from '@kit.ArkUI'
@Entry
@Component
struct Index {
aboutToAppear() {
// 开启全屏
window.getWindowExtension().setWindowLayoutFullScreen(true)
// 获取安全区域(避免刘海屏/圆角遮挡)
let safeArea = window.getWindowExtension().getStatusBarHeight()
console.log('状态栏高度:', safeArea)
}
build() {
Column() {
// 顶部内容延伸到状态栏下方
Image('banner.jpg')
.width('100%')
.height(250)
.objectFit(ImageFit.Cover)
}
.width('100%')
.height('100%')
}
}3. 安全区域适配
3.1 使用 systemSafeArea
typescript
// 通过 AppStorage 获取安全区域信息
let statusBarHeight: number = AppStorage.get('systemStatusBarHeight') ?? 0
let navigationBarHeight: number = AppStorage.get('systemNavigationBarHeight') ?? 0
let safeAreaInsets: SafeAreaInsets = AppStorage.get('systemSafeArea') ?? {
top: 0,
bottom: 0,
left: 0,
right: 0
}
@Entry
@Component
struct Index {
// 通过 AppStorage 获取安全区域
@State statusBarHeight: number = 0
aboutToAppear() {
// 监听系统安全区域变化
AppStorage.on('systemStatusBarHeight', (value: number) => {
this.statusBarHeight = value
})
// 开启全屏
window.getWindowExtension().setWindowLayoutFullScreen(true)
}
build() {
Column() {
// 预留状态栏高度
Blank()
.height(this.statusBarHeight)
// 内容区域
Image('banner.jpg')
.width('100%')
.height(200)
.objectFit(ImageFit.Cover)
Text('内容区域从安全区域开始')
.padding({ top: this.statusBarHeight })
}
.width('100%')
.height('100%')
}
}3.2 AppStorage 获取安全区域的方法
typescript
// 方式1:通过 window API
import { window } from '@kit.ArkUI'
let statusBarHeight = window.getWindowExtension().getStatusBarHeight()
let navigationBarHeight = window.getWindowExtension().getNavigationBarHeight()
// 方式2:通过 AppStorage(响应式,推荐)
let safeArea = AppStorage.get('systemSafeArea')4. 导航栏避让
4.1 底部导航栏避让
typescript
@Entry
@Component
struct Index {
@State safeAreaInsets: SafeAreaInsets = { top: 0, bottom: 0, left: 0, right: 0 }
aboutToAppear() {
window.getWindowExtension().setWindowLayoutFullScreen(true)
// 监听安全区域变化
AppStorage.on('systemSafeArea', (value: SafeAreaInsets) => {
this.safeAreaInsets = value
})
}
build() {
Column() {
// 顶部避让
Blank()
.height(this.safeAreaInsets.top)
// 主内容
Scroll() {
Column() {
ForEach(this.items, (item: string) => {
Text(item)
.fontSize(16fp)
.padding({ top: 12, bottom: 12 })
})
}
}
.width('100%')
.layoutWeight(1)
// 底部导航栏(在安全区域内)
Row() {
TabItem({ title: '首页', icon: $r('app.media.home') })
TabItem({ title: '发现', icon: $r('app.media.discover') })
TabItem({ title: '我的', icon: $r('app.media.profile') })
}
.height(56 + this.safeAreaInsets.bottom)
.padding({ bottom: this.safeAreaInsets.bottom })
.backgroundColor(Color.White)
}
.width('100%')
.height('100%')
}
}5. 刘海屏/圆角屏适配
5.1 检测刘海屏
typescript
import { window } from '@kit.ArkUI'
@Entry
@Component
struct Index {
@State hasNotch: boolean = false
aboutToAppear() {
// 检测是否有刘海屏
let notchScreenInfo = window.getWindowExtension().getNotchScreenInfo()
this.hasNotch = notchScreenInfo.hasNotch
if (this.hasNotch) {
console.log('刘海屏信息:', JSON.stringify(notchScreenInfo.notch))
}
}
build() {
Column() {
if (this.hasNotch) {
Text('检测到刘海屏,需要避让')
.fontColor(Color.Red)
}
// 内容从安全区域开始
Content()
}
}
}6. 状态栏颜色设置
6.1 状态栏文字颜色
typescript
import { window } from '@kit.ArkUI'
@Entry
@Component
struct Index {
aboutToAppear() {
window.getWindowExtension().setWindowLayoutFullScreen(true)
// 浅色状态栏文字(深色图标)
window.getWindowExtension().setColorMode(ColorMode.Light)
// 或深色状态栏文字(浅色图标)
// window.getWindowExtension().setColorMode(ColorMode.Dark)
}
build() {
// 内容
}
}6.2 状态栏背景色
typescript
// 通过设置顶部区域的颜色来实现
Column() {
Column()
.height(statusBarHeight)
.backgroundColor(Color.FromRGB(0x1A, 0x1A, 0x2E))
// 内容
}7. 完整的沉浸式示例
typescript
@Entry
@Component
struct ImmersivePage {
@State statusBarHeight: number = 0
@State navigationBarHeight: number = 0
@State safeArea: SafeAreaInsets = { top: 0, bottom: 0, left: 0, right: 0 }
aboutToAppear() {
// 开启全屏
window.getWindowExtension().setWindowLayoutFullScreen(true)
// 获取安全区域
AppStorage.on('systemStatusBarHeight', (value: number) => {
this.statusBarHeight = value
})
AppStorage.on('systemSafeArea', (value: SafeAreaInsets) => {
this.safeArea = value
})
AppStorage.on('systemNavigationBarHeight', (value: number) => {
this.navigationBarHeight = value
})
}
build() {
Column() {
// 状态栏避让区
Blank()
.height(this.statusBarHeight)
// 全屏 Banner
Stack() {
Image('banner.jpg')
.width('100%')
.height(200)
.objectFit(ImageFit.Cover)
Text('沉浸式标题')
.fontSize(24fp)
.fontColor(Color.White)
.position({ x: 16, y: this.statusBarHeight + 60 })
}
// 内容区域
Scroll() {
Column() {
ForEach(this.items, (item: string) => {
Text(item)
.fontSize(16fp)
.padding({ top: 12, bottom: 12, left: 16, right: 16 })
})
}
}
.width('100%')
.layoutWeight(1)
// 底部避让区
Blank()
.height(this.navigationBarHeight)
}
.width('100%')
.height('100%')
}
}8. 面试高频考点
Q1: 如何实现沉浸式状态栏?
回答:调用 window.setWindowLayoutFullScreen(true) 开启全屏,通过 AppStorage 获取 systemSafeArea 高度,给根布局设置 Padding 避让状态栏和导航栏。
Q2: 安全区域的作用?
回答:安全区域定义了屏幕的有效可视范围(排除状态栏、刘海屏、圆角、导航栏)。内容应该只在安全区域内,避免被系统 UI 遮挡。
Q3: 状态栏文字颜色如何设置?
回答:通过 window.getWindowExtension().setColorMode(ColorMode.Light/ColorMode.Dark) 设置浅色/深色状态栏文字模式。
🐱 小猫提示:沉浸式状态栏记住三步——开启全屏、获取安全区域、Padding 避让。安全区域用 AppStorage 响应式获取。