本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
沉浸式效果是提升用户体验的重要手段,通过调整状态栏、应用界面和导航条的显示效果来减少系统界面的突兀感。本文将全面介绍鸿蒙开发中实现沉浸式效果的技术方案、API使用。
一、沉浸式效果基础概念
1. 界面元素与区域划分
典型应用全屏窗口UI元素包括:
- 状态栏:显示系统信息(时间、电量等)
- 应用界面:主要内容展示区
- 导航条:底部操作区域
这些区域中,状态栏和导航条通常称为避让区,避让区之外的区域称为安全区
2. 设计要素
- UI元素避让处理:可交互元素应避开系统UI区域
- 视觉一致性:状态栏/导航条颜色应与界面元素协调
- 交互体验:不影响系统手势操作的同时保证内容完整展示
二、沉浸式实现方案
鸿蒙主要提供了三种实现沉浸式效果方案:
1. 窗口全屏布局方案
核心API
setWindowLayoutFullScreen()
:设置窗口全屏显示getWindowAvoidArea()
:获取避让区域信息on('avoidAreaChange')
:监听避让区域变化
实现步骤
- 设置窗口全屏:
// EntryAbility.ets
import { window } from '@kit.ArkUI';
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.getMainWindowSync().setWindowLayoutFullScreen(true)
.then(() => {
console.info('设置全屏成功');
});
}
2. 获取避让区域:
// 获取导航条避让区域
const avoidArea = window.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);
const bottomHeight = avoidArea.bottomRect.height;
// 获取状态栏避让区域
const systemAvoidArea = window.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
const topHeight = systemAvoidArea.topRect.height;
3. 动态调整布局:
// 监听避让区域变化
window.on('avoidAreaChange', (data) => {
if (data.type === window.AvoidAreaType.TYPE_SYSTEM) {
// 更新状态栏高度
AppStorage.setOrCreate('topRectHeight', data.area.topRect.height);
}
});
2. 安全区扩展方案
核心API
expandSafeArea()
:组件安全区扩展属性
实现方式
Image($r('app.media.background'))
.width('100%')
.height('100%')
.expandSafeArea(
[SafeAreaType.SYSTEM, SafeAreaType.CUTOUT], // 扩展类型
[SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM] // 扩展方向
)
参数说明:
SafeAreaType
枚举:SYSTEM
:系统默认避让区CUTOUT
:刘海屏挖孔区KEYBOARD
:软键盘区域
SafeAreaEdge
枚举:TOP
:顶部BOTTOM
:底部START
:起始边END
:结束边
3. 背景色统一方案
通过设置窗口背景色实现视觉沉浸:
// Ability中设置
onWindowStageCreate(windowStage: window.WindowStage) {
windowStage.getMainWindowSync()
.setWindowBackgroundColor('#F5F5F5'); // 与界面主色一致
}
三、高级功能实现
1. 动态隐藏系统UI
完全隐藏状态栏和导航条:
// 需要import window from '@kit.ArkUI'
window.getLastWindow(getContext())
.then(win => {
win.setWindowLayoutFullScreen(true);
win.setWindowSystemBarEnable(['status', 'navigation'], false);
});
2. 状态栏文字颜色控制
设置状态栏文字深色/浅色模式:
window.getLastWindow(getContext())
.then(win => {
win.setWindowSystemBarProperties({
statusBarContentColor: '#000000' // 黑色文字
});
});
3. 分场景适配方案
场景1:视频播放页 - 完全沉浸
aboutToAppear(): void {
window.getLastWindow(getContext())
.then(win => {
win.setWindowLayoutFullScreen(true);
win.setWindowSystemBarEnable([], false); // 全部隐藏
});
}
场景2:阅读页 - 半沉浸
aboutToAppear(): void {
window.getLastWindow(getContext())
.then(win => {
win.setWindowSystemBarProperties({
statusBarColor: '#F5F5F5',
navigationBarColor: '#F5F5F5',
statusBarContentColor: '#000000'
});
});
}
四、避坑指南
1. 常见问题解决
问题1:刘海屏内容遮挡
- 解决方案:
Column() {
// 内容区
}
.margin({ top: $r('app.float.status_bar_height') }) // 预留状态栏高度
问题2:键盘弹出布局错乱
- 解决方案:
TextArea()
.expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.BOTTOM])
2. 性能优化建议
- 避免频繁更新:沉浸式设置应在
onWindowStageCreate
或aboutToAppear
中完成 - 使用缓存:将
getWindowAvoidArea
结果缓存到AppStorage - 按需更新:非必要不调用
setWindowLayoutFullScreen
3. 多设备适配方案
通过条件判断适配不同设备:
import deviceInfo from '@ohos.deviceInfo';
const deviceType = deviceInfo.deviceType;
if (deviceType === 'phone') {
// 手机特定适配
} else if (deviceType === 'tablet') {
// 平板特定适配
}
五、完整示例:视频播放页沉浸实现
// VideoPlayerPage.ets
import window from '@kit.ArkUI';
@Entry
@Component
struct VideoPlayerPage {
@State isFullscreen: boolean = false;
build() {
Column() {
VideoPlayer({
src: 'video.mp4',
controller: this.videoController
})
.onClick(() => {
this.toggleFullscreen();
})
}
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
}
toggleFullscreen() {
this.isFullscreen = !this.isFullscreen;
window.getLastWindow(getContext())
.then(win => {
win.setWindowLayoutFullScreen(this.isFullscreen);
win.setWindowSystemBarEnable(['status', 'navigation'], !this.isFullscreen);
});
}
}
实现效果:
- 点击视频进入全屏沉浸模式
- 再次点击恢复常规显示
- 顶部状态栏自动适配
六、总结与版本适配建议
1. 方案对比
方案 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
窗口全屏 | 需要精确控制布局 | 灵活度高 | 实现复杂 |
安全区扩展 | 快速实现沉浸背景 | 简单易用 | 控制粒度粗 |
背景色统一 | 视觉一致性要求高 | 性能好 | 功能有限 |
2. 版本适配
- API 8+:支持基础沉浸式功能
- API 12+:新增
expandSafeArea
等高级特性 - NEXT版本:推荐使用声明式安全区控制