• Home
Name Date Size #Lines LOC

..--

AppScope/06-May-2025-3432

casesfeature/immersive/06-May-2025-1,9311,819

entry/06-May-2025-465440

hvigor/06-May-2025-2322

.gitignoreD06-May-2025133 1212

README.mdD06-May-202510.7 KiB217189

build-profile.json5D06-May-20251.4 KiB6060

code-linter.json5D06-May-2025957 3434

hvigorfile.tsD06-May-2025234 75

oh-package.json5D06-May-2025200 1110

ohosTest.mdD06-May-20251.1 KiB129

README.md

1# 沉浸式适配案例
2
3### 介绍
4
5开发应用沉浸式效果主要指通过调整状态栏、应用界面和导航条的显示效果来减少状态栏导航条等系统界面的突兀感,从而使用户获得最佳的UI体验。本案例分别针对Navigation、滚动、Web页、底部弹框等场景实现了沉浸式适配,且介绍了实现沉浸式适配的两种方案。
6
7### 效果图预览
8
9![immersive](./entry/src/main/resources/base/media/immersive.gif)
10
11**使用说明:**
12
131. 首页顶部是Navigation沉浸式,滑动商品列表是滚动场景沉浸式
142. 点击首页的banner进入web页展示Web页沉浸式
153. 点击商品进入商品详情页,展示普通页沉浸式
164. 点击商品详情页的商品评论弹出评论弹框展示底部弹框沉浸式
17
18
19### 实现思路
20页面的显示区域,默认不与系统设置的非安全区域比如状态栏、导航栏区域重叠,默认情况下开发者开发的界面都被布局在安全区域内。而要实现沉浸式效果,则需要设置组件绘制内容突破安全区域的限制。目前系统提供了两种方案:
211. [组件安全区方案](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-develop-apply-immersive-effects-V5#section202081847174413)
222. [窗口全屏布局方案](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-develop-apply-immersive-effects-V5#section15671730447)(此方案比较适合整个应用进行沉浸式使用,单个页面沉浸式建议使用“组件安全区方案”)
23
24#### 两种方案的实现案例如下:
25##### 1、通过设置[expandSafeArea](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-universal-attributes-expand-safe-area.md#expandsafearea)这个组件属性, 可支持组件在不改变布局情况下扩展其绘制区域至安全区外。
26
27###### Navigation沉浸式适配
28Navigation沉浸式需要区分不同场景,如果是整个页面的背景色设置在Navigation组件,则对Navigation组件设置expandSafeArea熟悉使其整体绘制延伸至状态栏和导航条。若页面顶部和底部背景色不一致,需分别处理,如本案例单独对顶部组件设置了expandSafeArea熟悉使其绘制延伸至状态栏。详情见[NavImmersive.ets](./casesfeature/immersive/src/main/ets/view/NavImmersive.ets)。
29```typescript
30Navigation(this.navPathStack) {
31   Column({ space: COLUM_SPACE }) {
32      ...
33   }
34   .backgroundColor($r("app.color.immersive_column_bg_color"))
35   .width('100%')
36    // 设置顶部绘制延伸至状态栏
37   .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
38   ...
39}
40```
41###### 滚动场景沉浸式适配
42滚动场景需要对每一个嵌套的带有滚动的组件设置expandSafeArea属性,使其视窗范围扩展至导航条。
431. 设置Scroller组件的视窗范围扩展至导航条。详情见[NavImmersive.ets](./casesfeature/immersive/src/main/ets/view/NavImmersive.ets)。
44```typescript
45Scroll() {
46 ...
47}
48.backgroundColor($r("app.color.immersive_list_bg_color"))
49.padding({ bottom: $r("app.integer.immersive_column_padding_bottom") })
50.width('100%')
51.layoutWeight(LAYOUT_WEIGHT)
52.scrollBar(BarState.Off)
53.align(Alignment.Top)
54// 将底部绘制延伸至导航条
55.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
56```
572. 设置GridRow组件的视窗范围扩展至导航条。详情见[GoodsList.ets](./casesfeature/immersive/src/main/ets/components/GoodsList.ets)。
58```typescript
59 GridRow({ gutter: { x: GUTTER_X, y: GUTTER_Y }, }) {
60   ...
61 }
62 .padding({
63   left: $r("app.integer.immersive_grid_row_padding"),
64   right: $r("app.integer.immersive_grid_row_padding"),
65   top: $r("app.integer.immersive_grid_row_padding"),
66   bottom: $r("app.integer.immersive_grid_row_padding")
67 })
68 .backgroundColor($r("app.color.immersive_list_bg_color"))
69 // 设置列表绘制延伸至状态栏
70 .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
71```
72###### Web沉浸式适配
73Web场景则需要分为两块,title以及Web页,分别对其进行处理,然后在Web页中设置网页元素对安全区进行避让
741. 设置Web组件绘制延伸至状态栏和导航条。详情见[WebImmersive.ets](./casesfeature/immersive/src/main/ets/view/WebImmersive.ets)。
75```typescript
76Web({ src: $rawfile('web_immersive.html'), controller: this.controller })
77   .width('100%')
78   .layoutWeight(1)
79      // 设置Web绘制延伸到状态栏和导航条
80   .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
81```
822. 设置网页在可视窗口中的布局方式,且让网页元素对导航条进行避让。详情见[web_immersive.html](./casesfeature/immersive/src/main/resources/rawfile/web_immersive.html)。
83```html
84...
85<meta name='viewport' content='viewport-fit=cover, width=device-width, initial-scale=1.0'>
86...
87<style>
88     ...
89     footer {
90         /* 网页元素对导航条进行避让 */
91         padding-bottom: env(safe-area-inset-bottom);
92     }
93</style>
94```
95
96##### 2、通过设置[setWindowLayoutFullScreen()](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/reference/apis-arkui/js-apis-window.md#setwindowlayoutfullscreen9)这个接口实现窗口强制全屏布局,再通过接口getWindowAvoidArea()和on('avoidAreaChange')获取并动态监听安全区域的高度信息,手动进行避让。
97###### 窗口全屏布局方案沉浸式适配示例
981. 设置窗口强制全屏布局。详情见[FullScreenImmersive.ets](./casesfeature/immersive/src/main/ets/view/FullScreenImmersive.ets)。
99```typescript
100window.getLastWindow(getContext(), (err, windowClass) => {
101  ...
102  // 设置窗口强制全屏布局
103  windowClass.setWindowLayoutFullScreen(true);
104  ...
105})
106```
1072. 获取状态栏和导航条的高度。详情见[FullScreenImmersive.ets](./casesfeature/immersive/src/main/ets/view/FullScreenImmersive.ets)。
108```typescript
109window.getLastWindow(getContext(), (err, windowClass) => {
110  ...
111  // 获取导航条高度
112  this.bottomHeight = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect.height;
113  // 获取状态栏高度
114  this.topHeight = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height;
115})
116```
1173. 对父组件设置padding,手动对安全区域进行避让。详情见[FullScreenImmersive.ets](./casesfeature/immersive/src/main/ets/view/FullScreenImmersive.ets)。
118```typescript
119Column() {
120  ...
121}
122.height('100%')
123.width('100%')
124.backgroundColor($r('app.color.immersive_background_color'))
125// 设置padding避让状态栏及导航条
126.padding({ top: px2vp(this.topHeight), bottom: px2vp(this.bottomHeight) })
127```
128###### 底部弹框沉浸式适配
129底部弹框沉浸式场景只需要处理导航条,需要获取导航条高度,手动对其进行避让。
1301. 获取导航条的高度。详情见[ImmersiveDialog.ets](./casesfeature/immersive/src/main/ets/dialog/ImmersiveDialog.ets)。
131```typescript
132window.getLastWindow(getContext(), (err, data) => {
133  const avoidAreaBottom = data.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);
134  this.bottomHeight = avoidAreaBottom.bottomRect.height;
135})
136```
1372. 设置弹框尾部元素对导航条进行避让。详情见[Comment.ets](./casesfeature/immersive/src/main/ets/components/Comment.ets)。
138```typescript
139...
140List({ space: Constants.COMMENT_SPACE, scroller: this.scroller }) {
141  // TODO: 高性能知识点: LazyForEach按需加载,提高加载性能。
142  LazyForEach(this.data, (item: number, index: number) => {
143    ListItem() {
144      this.commentItem(index + 1) // index from 1
145    }
146    // 设置弹框尾部元素对导航条进行避让
147    .margin({ bottom: index === this.data.totalCount() - 1 ? px2vp(this.bottomHeight) : 0 })
148  }, (item: number) => item.toString())
149}
150...
151```
152
153#### 高性能知识点
154
155**不涉及**
156
157### FAQ
1581. 使用[窗口全屏布局方案](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-develop-apply-immersive-effects-V5#section15671730447)进行沉浸式适配时出现窗口跳动。
159   答:setWindowLayoutFullScreen接口是将窗口强制全屏化,也即是当应用设置这个接口时会对所有页面生效。因此该方案只适用于全应用进行沉浸式适配,且所有页面都采用此种方案。如果是单页面适配沉浸式,推荐使用[组件安全区方案](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-develop-apply-immersive-effects-V5#section202081847174413)1602. 滚动场景使用[窗口全屏布局方案](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-develop-apply-immersive-effects-V5#section15671730447)进行沉浸式适配时,尾项不从导航条底部出现。
161   答:滚动场景需特殊处理,父组件只需避让状态栏,也即是只需要设置padding-top,然后对list的尾项做一个对导航条的避让,也即是设置尾项的margin-bottom。
162
163### 工程结构&模块类型
164
165```
166immersive                                       // har类型
167|---common
168|---|---Constants.ets                           // 常量
169|---components
170|---|---Comment.ets                             // 商品评论
171|---|---GoodsList.ets                           // 商品列表
172|---mock
173|---|---GoodsMock.ets                           // 商品列表mock数据
174|---model
175|---|---CommentDataSource.ets                   // 商品评论数据源
176|---|---GoodsModel.ets                          // 商品实体类
177|---dialog
178|---|---ImmersiveDialog.ets                     // 底部弹框沉浸式适配
179|---view
180|---|---WebImmersive.ets                        // Web沉浸式适配
181|---|---NavImmersive.ets                        // Navigation场景沉浸式适配,也是沉浸式适配场景入口
182|---|---FullScreenImmersive.ets                 // 窗口全屏布局方案示例
183|---|---GoodsDetails.ets                        // 商品详情页
184```
185
186### 参考资料
187
1881. [开发应用沉浸式效果](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-develop-apply-immersive-effects-V5)
1892. [网页中安全区域计算和避让适配](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/web/web-safe-area-insets.md)
1903. [导航条](https://developer.huawei.com/consumer/cn/doc/design-guides/navigation-0000001957075737)
191
192### 相关权限
193
194不涉及
195
196### 依赖
197
198不涉及
199
200### 约束与限制
201
2021. 本示例仅支持标准系统上运行。
203
2042. 本示例已适配API version 12版本SDK。
205
2063. 本示例需要使用DevEco Studio 5.0.0 Release及以上版本才可编译运行。
207
208### 下载
209
210如需单独下载本工程,执行如下命令:
211```bash
212git init
213git config core.sparsecheckout true
214echo /code/UI/Immersive/ > .git/info/sparse-checkout
215git remote add origin https://gitee.com/openharmony/applications_app_samples.git
216git pull origin master
217```