鸿蒙沉浸式标题栏实践

452 阅读1分钟

根据鸿蒙官网文档,应用沉浸式效果有2种实现方式:

1.全屏,如果你不想ui内容和状态栏(手机信号电量那一栏)导航栏(小白条或者三大金刚键那条)重叠,就自己写padding让出对应区域

2.安全区,使用安全区的话,你的ui布局会默认让出状态栏和导航栏区域,此时如果你想实现沉浸效果,可以给window设置个背景颜色,也可以使用expandSafeArea。expandSafeArea简单地说,就是让你的ui顶部或者底部的背景扩展到状态栏和导航栏

以上2点不赘述,具体看官网文档

我的项目中想实现一个通用的标题栏组件,如果不实现沉浸效果,那是这样的:

image.png

这显然不行,老板会骂人的

那就使用expandSafeArea把标题栏的背景蓝色扩展到状态栏试试,效果和代码如下:

image.png

import { router, window, display } from '@kit.ArkUI';

@Preview
@Component
export struct TitleBar {
  @Prop title: string;
  @State statusHeightPercent: number = 0


  build() {
    Row() {
      Image($r('app.media.back'))
        .width(25).height(25)
        .margin({ left: 10 }).objectFit(ImageFit.Contain)
        .onClick(() => {
          router.back()
        })
      Text(this.title)
        .layoutWeight(1).height('100%').textAlign(TextAlign.Center)
        .fontSize(22).fontColor($r('app.color.white')).margin({right:35})
    }
    .backgroundColor($r('app.color.color_app'))
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
    .height(45)
    .width('100%')

  }
}

什么玩意,蓝色怎么只到状态栏?(这里说明一下,标题栏文字和图标都是白色,所以没背景后就看不见了,这里我也被坑了一把)

然后,发现文档里有这么一段描述:

  • 配置expandSafeArea属性组件进行绘制扩展时,需要关注组件不能配置固定宽高尺寸,百分比除外。

为啥?为啥只能用百分比?

我的标题栏高度是45,只能艰难地换算成百分比,代码和实际效果如下,总算是实现了效果

image.png

import { router, window, display } from '@kit.ArkUI';

@Preview
@Component
export struct TitleBar {
  @Prop title: string;
  @State statusHeightPercent: number = 0

  aboutToAppear(): void {
    window.getLastWindow(getContext())
      .then(win => {
        //状态栏高度
        let statusHeight = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height
        //导航栏高度
        let navigationHeight = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect.height

        //计算标题栏高度百分比,45是标题栏的高度vp值
        let screen = display.getDefaultDisplaySync()
        this.statusHeightPercent = 45 * 100 * screen.densityPixels / (screen.availableHeight - statusHeight -navigationHeight)
      })
  }

  build() {
    Row() {
      Image($r('app.media.back'))
        .width(25).height(25)
        .margin({ left: 10 }).objectFit(ImageFit.Contain)
        .onClick(() => {
          router.back()
        })
      Text(this.title)
        .layoutWeight(1).height('100%').textAlign(TextAlign.Center)
        .fontSize(22).fontColor($r('app.color.white')).margin({right:35})
    }
    .backgroundColor($r('app.color.color_app'))
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
    .height(this.statusHeightPercent + '%')
    .width('100%')

  }
}