首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >鸿蒙开发实战案例:沉浸式适配案例

鸿蒙开发实战案例:沉浸式适配案例

原创
作者头像
小帅聊鸿蒙
发布2025-03-02 21:39:46
发布2025-03-02 21:39:46
2870
举报
文章被收录于专栏:鸿蒙开发笔记鸿蒙开发笔记

介绍

开发应用沉浸式效果主要指通过调整状态栏、应用界面和导航条的显示效果来减少状态栏导航条等系统界面的突兀感,从而使用户获得最佳的UI体验。本案例分别针对Navigation、滚动、Web页、底部弹框等场景实现了沉浸式适配,且介绍了实现沉浸式适配的两种方案。

效果图预览

使用说明:

  1. 首页顶部是Navigation沉浸式,滑动商品列表是滚动场景沉浸式
  2. 点击首页的banner进入web页展示Web页沉浸式
  3. 点击商品进入商品详情页,展示普通页沉浸式
  4. 点击商品详情页的商品评论弹出评论弹框展示底部弹框沉浸式

实现思路

页面的显示区域,默认不与系统设置的非安全区域比如状态栏、导航栏区域重叠,默认情况下开发者开发的界面都被布局在安全区域内。而要实现沉浸式效果,则需要设置组件绘制内容突破安全区域的限制。目前系统提供了两种方案:

  1. 组件安全区方案
  2. 窗口全屏布局方案(此方案比较适合整个应用进行沉浸式使用,单个页面沉浸式建议使用“组件安全区方案”)
两种方案的实现案例如下:
1、通过设置expandSafeArea这个组件属性, 可支持组件在不改变布局情况下扩展其绘制区域至安全区外。
Navigation沉浸式适配

Navigation沉浸式需要区分不同场景,如果是整个页面的背景色设置在Navigation组件,则对Navigation组件设置expandSafeArea熟悉使其整体绘制延伸至状态栏和导航条。若页面顶部和底部背景色不一致,需分别处理,如本案例单独对顶部组件设置了expandSafeArea熟悉使其绘制延伸至状态栏。详情见NavImmersive.ets。

代码语言:typescript
复制
Navigation(this.navPathStack) {
   Column({ space: COLUM_SPACE }) {
      ...
   }
   .backgroundColor($r("app.color.immersive_column_bg_color"))
   .width('100%')
    // 设置顶部绘制延伸至状态栏
   .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
   ...
}
滚动场景沉浸式适配

滚动场景需要对每一个嵌套的带有滚动的组件设置expandSafeArea属性,使其视窗范围扩展至导航条。

  1. 设置Scroller组件的视窗范围扩展至导航条。详情见NavImmersive.ets。
代码语言:typescript
复制
Scroll() {
 ...
}
.backgroundColor($r("app.color.immersive_list_bg_color"))
.padding({ bottom: $r("app.integer.immersive_column_padding_bottom") })
.width('100%')
.layoutWeight(LAYOUT_WEIGHT)
.scrollBar(BarState.Off)
.align(Alignment.Top)
// 将底部绘制延伸至导航条
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
  1. 设置GridRow组件的视窗范围扩展至导航条。详情见GoodsList.ets。
代码语言:typescript
复制
 GridRow({ gutter: { x: GUTTER_X, y: GUTTER_Y }, }) {
   ...
 }
 .padding({
   left: $r("app.integer.immersive_grid_row_padding"),
   right: $r("app.integer.immersive_grid_row_padding"),
   top: $r("app.integer.immersive_grid_row_padding"),
   bottom: $r("app.integer.immersive_grid_row_padding")
 })
 .backgroundColor($r("app.color.immersive_list_bg_color"))
 // 设置列表绘制延伸至状态栏
 .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
Web沉浸式适配

Web场景则需要分为两块,title以及Web页,分别对其进行处理,然后在Web页中设置网页元素对安全区进行避让

  1. 设置Web组件绘制延伸至状态栏和导航条。详情见WebImmersive.ets。
代码语言:typescript
复制
Web({ src: $rawfile('web_immersive.html'), controller: this.controller })
   .width('100%')
   .layoutWeight(1)
      // 设置Web绘制延伸到状态栏和导航条
   .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
  1. 设置网页在可视窗口中的布局方式,且让网页元素对导航条进行避让。详情见web_immersive.html。
代码语言:html
复制
...
<meta name='viewport' content='viewport-fit=cover, width=device-width, initial-scale=1.0'>
...
<style>
     ...
     footer {
         /* 网页元素对导航条进行避让 */
         padding-bottom: env(safe-area-inset-bottom);
     }
</style>
DD一下:欢迎大家关注公众号<程序猿百晓生>,可以了解到一下知识点。
代码语言:erlang
复制
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案) 
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......
2、通过设置setWindowLayoutFullScreen()这个接口实现窗口强制全屏布局,再通过接口getWindowAvoidArea()和on('avoidAreaChange')获取并动态监听安全区域的高度信息,手动进行避让。
窗口全屏布局方案沉浸式适配示例
  1. 设置窗口强制全屏布局。详情见FullScreenImmersive.ets。
代码语言:typescript
复制
window.getLastWindow(getContext(), (err, windowClass) => {
  ...
  // 设置窗口强制全屏布局
  windowClass.setWindowLayoutFullScreen(true);
  ...
})
  1. 获取状态栏和导航条的高度。详情见FullScreenImmersive.ets。
代码语言:typescript
复制
window.getLastWindow(getContext(), (err, windowClass) => {
  ...
  // 获取导航条高度
  this.bottomHeight = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect.height;
  // 获取状态栏高度
  this.topHeight = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height;
})
  1. 对父组件设置padding,手动对安全区域进行避让。详情见FullScreenImmersive.ets。
代码语言:typescript
复制
Column() {
  ...
}
.height('100%')
.width('100%')
.backgroundColor($r('app.color.immersive_background_color'))
// 设置padding避让状态栏及导航条
.padding({ top: px2vp(this.topHeight), bottom: px2vp(this.bottomHeight) })
底部弹框沉浸式适配

底部弹框沉浸式场景只需要处理导航条,需要获取导航条高度,手动对其进行避让。

  1. 获取导航条的高度。详情见ImmersiveDialog.ets。
代码语言:typescript
复制
window.getLastWindow(getContext(), (err, data) => {
  const avoidAreaBottom = data.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);
  this.bottomHeight = avoidAreaBottom.bottomRect.height;
})
  1. 设置弹框尾部元素对导航条进行避让。详情见Comment.ets。
代码语言:typescript
复制
...
List({ space: Constants.COMMENT_SPACE, scroller: this.scroller }) {
  // TODO: 高性能知识点: LazyForEach按需加载,提高加载性能。
  LazyForEach(this.data, (item: number, index: number) => {
    ListItem() {
      this.commentItem(index + 1) // index from 1
    }
    // 设置弹框尾部元素对导航条进行避让
    .margin({ bottom: index === this.data.totalCount() - 1 ? px2vp(this.bottomHeight) : 0 })
  }, (item: number) => item.toString())
}
...
高性能知识点

不涉及

FAQ

  1. 使用窗口全屏布局方案进行沉浸式适配时出现窗口跳动。 答:setWindowLayoutFullScreen接口是将窗口强制全屏化,也即是当应用设置这个接口时会对所有页面生效。因此该方案只适用于全应用进行沉浸式适配,且所有页面都采用此种方案。如果是单页面适配沉浸式,推荐使用组件安全区方案。
  2. 滚动场景使用窗口全屏布局方案进行沉浸式适配时,尾项不从导航条底部出现。 答:滚动场景需特殊处理,父组件只需避让状态栏,也即是只需要设置padding-top,然后对list的尾项做一个对导航条的避让,也即是设置尾项的margin-bottom。

模块依赖

动态路由模块

工程结构&模块类型

代码语言:shell
复制
immersive                                       // har类型
|---common                                   
|---|---Constants.ets                           // 常量
|---components
|---|---Comment.ets                             // 商品评论
|---|---GoodsList.ets                           // 商品列表
|---mock
|---|---GoodsMock.ets                           // 商品列表mock数据
|---model
|---|---CommentDataSource.ets                   // 商品评论数据源
|---|---GoodsModel.ets                          // 商品实体类
|---dialog
|---|---ImmersiveDialog.ets                     // 底部弹框沉浸式适配
|---view                                      
|---|---WebImmersive.ets                        // Web沉浸式适配
|---|---NavImmersive.ets                        // Navigation场景沉浸式适配,也是沉浸式适配场景入口
|---|---FullScreenImmersive.ets                 // 窗口全屏布局方案示例
|---|---GoodsDetails.ets                        // 商品详情页

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力;
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识;
  • 想要获取更多完整鸿蒙最新学习知识点,可关注B站:码牛课堂;

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 效果图预览
  • 实现思路
    • 两种方案的实现案例如下:
    • DD一下:欢迎大家关注公众号<程序猿百晓生>,可以了解到一下知识点。
    • 高性能知识点
  • FAQ
  • 模块依赖
  • 工程结构&模块类型
  • 写在最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档