1、概 述
本文是接着上篇文章 鸿蒙UI开发——基于全屏方案实现沉浸式界面 的继续讨论。除了全屏方案实现沉浸式界面外,我们还可以使用组件安全区的方案。
当我们没有使用setWindowLayoutFullScreen()接口设置窗口为全屏布局时,默认使用的策略就是组件安全区布局方式。即:
【应用在默认情况下窗口背景绘制范围是全屏,但UI元素被限制在安全区内(自动排除状态栏和导航条)进行布局,来避免界面元素被状态栏和导航条遮盖】
示意图如下:

我们将按业务场景去分析基于组件安全区的沉浸式界面的开发。
2、状态栏和导航条颜色相同场景
针对有些APP,状态栏和导航条颜色可能相同,例如如下效果:

针对这种场景,我们可以通过设置窗口的背景色来实现沉浸式效果,设置方式为:setWindowBackgroundColor() 【将窗口的颜色和应用的颜色设置为一致】
Ability中设置window的背景色代码如下(请注意14行代码):
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';import { window } from '@kit.ArkUI';export default class EntryAbility extends UIAbility {// ...onWindowStageCreate(windowStage: window.WindowStage): void {windowStage.loadContent('pages/Index', (err, data) => {if (err.code) {return;}// 设置全窗颜色和应用元素颜色一致windowStage.getMainWindowSync().setWindowBackgroundColor('#008000');});}}
组件中的背景色设置代码如下(请注意35行代码):
// xxx.ets@Entry@Componentstruct Example {build() {Column() {Row() {Text('ROW1').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('ROW2').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('ROW3').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('ROW4').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('ROW5').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('ROW6').fontSize(40)}.backgroundColor(Color.Orange).padding(20)}.width('100%').height('100%').alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.SpaceBetween).backgroundColor('#008000')}}
实现效果如下:

3、状态栏和导航条颜色不同场景
状态栏和导航条颜色不同时,可以使用expandSafeArea属性扩展安全区域属性进行调整。示例代码如下:
// xxx.ets@Entry@Componentstruct Example {build() {Column() {Row() {Text('Top Row').fontSize(40).textAlign(TextAlign.Center).width('100%')}.backgroundColor('#F08080')// 设置顶部绘制延伸到状态栏.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])Row() {Text('ROW2').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('ROW3').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('ROW4').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('ROW5').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('Bottom Row').fontSize(40).textAlign(TextAlign.Center).width('100%')}.backgroundColor(Color.Orange)// 设置底部绘制延伸到导航条.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])}.width('100%').height('100%').alignItems(HorizontalAlign.Center).backgroundColor('#008000').justifyContent(FlexAlign.SpaceBetween)}}
效果如下:

| 【扩展安全区域属性原理】
|
4、背景图和视频场景
设置背景图、视频控件大小为安全区域大小并配置expandSafeArea属性。
// xxx.ets@Entry@Componentstruct SafeAreaExample1 {build() {Stack() {Image($r('app.media.bg')).height('100%').width('100%').expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM]) // 图片组件的绘制区域扩展至状态栏和导航条。}.height('100%').width('100%')}}
效果图如下:

5、滚动类场景
场景需求:需要List滚动类组件滚动过程中元素可以和导航条重合,滚动至底部时,元素在导航条上面需要避让。示意图如下:

由于expandSafeArea不改变子节点布局,因此,List等滚动类组件可以调用expandSafeArea,延伸List组件视图窗口大小而不改变ListItem内在布局。实现ListItem在滑动过程中显示在导航条下,但滚动至最后一个时显示在导航条上。
开发示例如下:
step 1 : 配置窗口整体底色
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';import { window } from '@kit.ArkUI';export default class EntryAbility extends UIAbility {// ...onWindowStageCreate(windowStage: window.WindowStage): void {windowStage.loadContent('pages/Index', (err, data) => {if (err.code) {return;}windowStage.getMainWindowSync().setWindowBackgroundColor('#DCDCDC'); // 配置窗口整体底色});}}
step 2 : 界面代码展示
// xxx.ets@Entry@Componentstruct ListExample {private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]build() {Column() {List({ space: 20, initialIndex: 0 }) {ForEach(this.arr, (item: number) => {ListItem() {Text('' + item).width('100%').height(100).fontSize(16).textAlign(TextAlign.Center).borderRadius(10).backgroundColor(0xFFFFFF)}}, (item: string) => item)}.listDirection(Axis.Vertical) // 排列方向.scrollBar(BarState.Off).friction(0.6).divider({ strokeWidth: 2, color: 0xFFFFFF, startMargin: 20, endMargin: 20 }) // 每行之间的分界线.edgeEffect(EdgeEffect.Spring) // 边缘效果设置为Spring.width('90%')// List组件的视窗范围扩展至导航条。.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])}.width('100%').height('100%').padding({ top: 15 })}}
6、底部页签场景
场景需求:页签背景色能够延伸到导航条区域,但页签内部可操作元素需要在导航条之上。

针对底部的页签部分,Navigation组件和Tabs组件默认实现了页签的延伸处理,我们使用时只需要保证Navigation和Tabs组件的底部边界和底部导航条重合即可。
若我们显式调用expandSafeArea接口,则安全区效果由expandSafeArea参数指定。
如果我们没有使用Navigation和Tab组件而是采用自定义方式实现页签的场景,可以针对底部元素设置expandSafeArea属性实现底部元素的背景扩展。
顶部和底部UI元素未设置和设置expandSafeArea属性效果对比如下:

沉浸式实现代码如下:
// xxx.ets@Entry@Componentstruct VideoCreateComponent {build() {Column() {Row() {Text('Top Row').fontSize(40).textAlign(TextAlign.Center).width('100%')}.backgroundColor('#F08080')// 设置顶部绘制延伸到状态栏.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])Row() {Text('ROW2').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('ROW3').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('ROW4').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('ROW5').fontSize(40)}.backgroundColor(Color.Orange).padding(20)Row() {Text('Bottom Row').fontSize(40).textAlign(TextAlign.Center).width('100%')}.backgroundColor(Color.Orange)// 设置底部绘制延伸到导航条.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])}.width('100%').height('100%').alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.SpaceBetween).backgroundColor(Color.Green)}}
7、图文场景
当状态栏元素和底部导航条元素不同时,无法单纯通过窗口背景色或者背景图组件延伸实现,此时需要对顶部元素和底部元素分别配置expandSafeArea属性,顶部元素配置expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP]),底部元素配置expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.BOTTOM])。
代码如下:
@Entry@Componentstruct Index {build() {Swiper() {Column() {Image($r('app.media.start')).height('50%').width('100%')// 设置图片延伸到状态栏.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])Column() {Text('HarmonyOS 第一课').fontSize(32).margin(30)Text('通过循序渐进的学习路径,无经验和有经验的开发者都可以掌握ArkTS语言声明式开发范式,体验更简洁、更友好的HarmonyOS应用开发旅程。').fontSize(20).margin(20)}.height('50%').width('100%').backgroundColor(Color.White)// 设置文本内容区背景延伸到导航栏.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])}}.width('100%').height('100%')// 关闭Swiper组件默认的裁切效果以便子节点可以绘制在Swiper外。.clip(false)}}
实现效果如下:

鸿蒙UI基于组件安全区的沉浸式开发
420

被折叠的 条评论
为什么被折叠?



