【HarmonyOS Next】原生沉醉式界面

打印 上一主题 下一主题

主题 1016|帖子 1016|积分 3048

背景

在实际项目中,为了软件使用整体色调看起来统一,一般顶部和底部的颜色必要铺满整个手机屏幕。因此,这篇帖子是介绍设置的方法,也是应用沉醉式结果。如下图:底部的绿色延伸到上面的状态栏和下面的导航栏

UI

在鸿蒙应用中,全屏UI元素分为状态栏、应用界面和导航栏。

一般实现应用沉醉式结果由两种方式:


  • 窗口全屏布局方案:调整布局体系为全屏布局,界面元素延伸到状态栏和导航条地区实现沉醉式结果。
  • 组件延伸方案:组件布局在应用界面地区,通过接口方法延伸到状态栏和导航栏。
窗口全屏布局方案


  • 新建展示页面,并使用@StorageProp界说页面内容的顶部偏移和底部偏移属性
  1. @Entry
  2. @Component
  3. struct Index {
  4.   @StorageProp('bottomRectHeight')
  5.   bottomRectHeight: number = 0;
  6.   @StorageProp('topRectHeight')
  7.   topRectHeight: number = 0;
  8.   build() {
  9.     Row() {
  10.       Column() {
  11.         Row() {
  12.           Text('DEMO-ROW1').fontSize(40)
  13.         }.backgroundColor(Color.Orange).padding(20)
  14.         Row() {
  15.           Text('DEMO-ROW2').fontSize(40)
  16.         }.backgroundColor(Color.Orange).padding(20)
  17.         Row() {
  18.           Text('DEMO-ROW3').fontSize(40)
  19.         }.backgroundColor(Color.Orange).padding(20)
  20.         Row() {
  21.           Text('DEMO-ROW4').fontSize(40)
  22.         }.backgroundColor(Color.Orange).padding(20)
  23.         Row() {
  24.           Text('DEMO-ROW5').fontSize(40)
  25.         }.backgroundColor(Color.Orange).padding(20)
  26.         Row() {
  27.           Text('DEMO-ROW6').fontSize(40)
  28.         }.backgroundColor(Color.Orange).padding(20)
  29.       }
  30.       .width('100%')
  31.       .height('100%')
  32.       .alignItems(HorizontalAlign.Center)
  33.       .justifyContent(FlexAlign.SpaceBetween)
  34.       .backgroundColor('#008000')
  35.       // top数值与状态栏区域高度保持一致;bottom数值与导航条区域高度保持一致
  36.       .padding({ top: px2vp(this.topRectHeight), bottom: px2vp(this.bottomRectHeight) })
  37.     }
  38.   }
  39. }
复制代码

  • 在EntryAbility的onWindowStageCreate方法中,调用window.Window.setWindowLayoutFullScreen方法设置窗口全屏。
  1. let windowClass: window.Window = windowStage.getMainWindowSync();
  2. let isLayoutFullScreen = true;
  3.     windowClass.setWindowLayoutFullScreen(isLayoutFullScreen).then(() => {
  4.       console.info('Succeeded in setting the window layout to full-screen mode.');
  5.     }).catch((err: BusinessError) => {
  6.       console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err));
  7.     });
复制代码

  • 为了避免构件被挡住,根据导航条和状态栏的高度,修改bottomRectHeight和topRectHeight的数值。
  1.     //获取导航栏高度
  2.     let bottomRectHeight = windowClass
  3.       .getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR)
  4.       .bottomRect
  5.       .height;
  6.     AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);
  7.     // 获取状态栏区域高度
  8.     let topRectHeight = windowClass
  9.       .getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM)
  10.       .topRect
  11.       .height;
  12.     AppStorage.setOrCreate('topRectHeight', topRectHeight);
复制代码

  • 再设置页面监听,动态修改bottomRectHeight和topRectHeight的数值。
  1. windowClass.on('avoidAreaChange', (data) => {
  2.       if (data.type === window.AvoidAreaType.TYPE_SYSTEM) {
  3.         let topRectHeight = data.area.topRect.height;
  4.         AppStorage.setOrCreate('topRectHeight', topRectHeight);
  5.       } else if (data.type == window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR) {
  6.         let bottomRectHeight = data.area.bottomRect.height;
  7.         AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);
  8.       }
  9.     });
复制代码
EntryAbility完整代码

仅必要修改onWindowStageCreate方法
  1. onWindowStageCreate(windowStage: window.WindowStage): void {    // Main window is created, set main page for this ability    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');    windowStage.loadContent('pages/Index', (err) => {      if (err.code) {        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');        return;      }      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');    });    // 获取应用主窗口    let windowClass: window.Window = windowStage.getMainWindowSync();    // 设置窗口全屏    let isLayoutFullScreen = true;    windowClass.setWindowLayoutFullScreen(isLayoutFullScreen).then(() => {      console.info('Succeeded in setting the window layout to full-screen mode.');    }).catch((err: BusinessError) => {      console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err));    });    //获取导航栏高度
  2.     let bottomRectHeight = windowClass
  3.       .getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR)
  4.       .bottomRect
  5.       .height;
  6.     AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);
  7.     // 获取状态栏区域高度
  8.     let topRectHeight = windowClass
  9.       .getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM)
  10.       .topRect
  11.       .height;
  12.     AppStorage.setOrCreate('topRectHeight', topRectHeight);
  13.     // 注册监听函数,动态获取避让地区数据    windowClass.on('avoidAreaChange', (data) => {
  14.       if (data.type === window.AvoidAreaType.TYPE_SYSTEM) {
  15.         let topRectHeight = data.area.topRect.height;
  16.         AppStorage.setOrCreate('topRectHeight', topRectHeight);
  17.       } else if (data.type == window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR) {
  18.         let bottomRectHeight = data.area.bottomRect.height;
  19.         AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);
  20.       }
  21.     });
  22.   }
复制代码
组件延伸方案

使用expandSafeArea方法来实现。
  1. expandSafeArea(types?: Array<SafeAreaType>, edges?: Array<SafeAreaEdge>): T;
复制代码


  • types:配置扩展安全地区的类型。SafeAreaType罗列类型,SYSTEM是体系默认非安全地区,包罗状态栏、导航栏;CUTOUT是设备的非安全地区,例如刘海屏或挖孔屏地区;KEYBOARD是软键盘地区,组件不避让键盘。
  • edges:扩展安全地区的方向。
代码

通过颜色对比,可以看出组件延伸结果。


  • column:背景颜色设置为橘色,从图片可以看出只能在安全地区内显示。
  • list:背景颜色设置为黄色,从图片可以看出已经延伸至导航条和状态栏了。
  • Text:背景颜色设置成红色,就可以看到整个组件的滑动过程.

  1. @Entry
  2. @Component
  3. struct ExamplePage {
  4.   private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  5.   build() {
  6.     Column() {
  7.       List({ space: 20, initialIndex: 0 }) {
  8.         ForEach(this.arr, (item: number) => {
  9.           ListItem() {
  10.             Text('' + item)
  11.               .width('100%')
  12.               .height(100)
  13.               .fontSize(16)
  14.               .textAlign(TextAlign.Center)
  15.               .borderRadius(10)
  16.               .backgroundColor(Color.Red)
  17.           }
  18.         }, (item: number) => item.toString())
  19.       }
  20.       .listDirection(Axis.Vertical) // 排列方向
  21.       .scrollBar(BarState.Off)
  22.       .friction(0.6)
  23.       .divider({
  24.         strokeWidth: 2,
  25.         color: 0xFFFFFF,
  26.         startMargin: 20,
  27.         endMargin: 20
  28.       }) // 每行之间的分界线
  29.       .edgeEffect(EdgeEffect.Spring) // 边缘效果设置为Spring
  30.       .width('90%')
  31.       .backgroundColor(Color.Yellow)
  32.       // List组件的视窗范围扩展至导航条。
  33.       .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
  34.     }
  35.     .width('100%')
  36.     .height('100%')
  37.     .backgroundColor(Color.Orange)
  38.   }
  39. }
复制代码
总结

如果不是全部界面都必要实现沉醉式布局时,可以通过组件延伸方案去实现部门组件的沉醉式布局。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天空闲话

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表