HarmonyOS鸿蒙Next中有一个页面的滚动内容区容器高度延伸到底部小白条安全区如何解决

HarmonyOS鸿蒙Next中有一个页面的滚动内容区容器高度延伸到底部小白条安全区如何解决 使用了全局应用沉浸式,使用scroll做了个页面滚动内容显示,在scroll下加了padding并未避让导航栏并未生效是为什么?

6 回复

可参考 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-develop-apply-immersive-effects#窗口全屏布局方案 ,通过setWindowLayoutFullScreen()实现全局沉浸式再通过接口getWindowAvoidArea()和on(‘avoidAreaChange’)获取并动态监听避让区域的变更信息,页面布局根据避让区域信息进行动态调整。Scroll 是滚动容器,内容区会被裁剪 / 滚动,自身 padding 只影响内部内容,不会改变 Scroll 组件本身在屏幕的占位所以并不会生效,可在scroll父组件加padding就可以起到避让导航条的效果可参考EntryAbility:

onWindowStageCreate(windowStage: window.WindowStage): void {
    console.info('onWindowStageCreate');

    let windowClass: window.Window | undefined = undefined;

    windowStage.getMainWindow((err: BusinessError, data) => {
      const errCode: number = err.code;
      if (errCode) {
        console.error(`Failed to obtain the main window. Cause code: ${err.code}, message: ${err.message}`);
        return;
      }
      windowClass = data;
      let isLayoutFullScreen = true;
      try {
        let promise = windowClass.setWindowLayoutFullScreen(isLayoutFullScreen);
        promise.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 code: ${err.code}, message: ${err.message}`);
        });
        // EntryAbility.ets
        // 2. 获取布局避让遮挡的区域
        let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; // 此处以导航条避让为例
        let avoidArea = windowClass.getWindowAvoidArea(type);
        let bottomRectHeight = avoidArea.bottomRect.height; // 获取到导航区域的高度
        AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);
        type = window.AvoidAreaType.TYPE_SYSTEM; // 以状态栏避让为例
        avoidArea = windowClass.getWindowAvoidArea(type);
        let topRectHeight = avoidArea.topRect.height; // 获取状态栏区域高度
        AppStorage.setOrCreate('topRectHeight', topRectHeight);// EntryAbility.ets
        // 3. 注册监听函数,动态获取避让区域数据
        windowClass.on('avoidAreaChange', (data) => {
          if (data.type === window.AvoidAreaType.TYPE_SYSTEM) {
            let topRectHeight = data.area.topRect.height;
            AppStorage.setOrCreate('topRectHeight', topRectHeight);
          } else if (data.type == window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR) {
            let bottomRectHeight = data.area.bottomRect.height;
            AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);
          }
        });
      } catch (exception) {
        console.error(`Failed to set the window layout to full-screen mode. Cause code: ${exception.code}, message: ${exception.message}`);
      }
    });
    // Main window is created, set main page for this ability
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
        return;
      }
      hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
    });

index:

// xxx.ets

@Entry
@Component
struct ScrollExample {
  @StorageProp('bottomRectHeight')
  bottomRectHeight: number = 0;
  @StorageProp('topRectHeight')
  topRectHeight: number = 0;
  scroller: Scroller = new Scroller()
  private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9]
  build() {
    Stack({ alignContent: Alignment.TopStart }) {
      Scroll(this.scroller) {
        Column() {
          ForEach(this.arr, (item: number) => {
            Stack() {
              Text('Display Content ' + item.toString()).fontSize(30)
            }
            .width('80%').padding(20).borderRadius(15).backgroundColor(Color.White).margin({ top:30, bottom:30 })
          }, (item: string) => item)
        }.width('100%').backgroundColor('rgb(213,213,213)')
      }.backgroundColor('rgb(213,213,213)')
    }.width('100%').height('100%')
    .padding({bottom:this.getUIContext().px2vp(this.bottomRectHeight)})
  }
}

更多关于HarmonyOS鸿蒙Next中有一个页面的滚动内容区容器高度延伸到底部小白条安全区如何解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


安全区

你这里的现象本质是:开了全局沉浸式后,页面布局坐标系会延伸到系统手势条/导航栏区域,单纯给 Scroll 自己加 padding 往往不会作用到“可滚动内容的末尾留白”(尤其是内容在 Scroll 里又包了一层 Column/Stack 时)。

建议按下面两种思路之一处理(都不需要贴任何隐私文件):

A)把 bottom padding 加到 Scroll 的“内容容器”上(而不是 Scroll 组件本身)

Scroll() {
  Column() {
    // ...你的内容
  }
  .padding({ bottom: 16 /* + 安全区高度 */ })
}

B)用系统安全区能力做避让(HarmonyOS 5/6 推荐)

  • 如果只想让内容不被底部系统区域遮挡:优先用 safeAreaPadding / 结合 getWindowAvoidArea 取到底部安全区高度,再加到内容容器的 paddingBottom。
  • 如果你是刻意要“延伸到安全区”,再配合 expandSafeArea 使用;否则不要开 expandSafeArea,避免把内容顶到小白条下面。

你现在的结构大概是 Scroll { xxx } 还是 Scroll { Column { ... } }?以及是全局沉浸式还是仅该页面沉浸式?把这两点(不含截图里的个人信息)补充一下,我可以给你一个更精确的写法。

试试安全区,

在HarmonyOS鸿蒙Next中,可通过设置容器的expandSafeArea属性为[SafeAreaType.SYSTEM]且指定[SafeAreaEdge.BOTTOM],或者使用SafeAreaCapability组件包裹滚动内容区,并设置其safeAreaTypes[SafeAreaType.SYSTEM]edges[SafeAreaEdge.BOTTOM],来避免内容延伸到底部小白条。

在全局沉浸式下,滚动容器(Scroll)直接加固定 padding 无法避让导航栏,因为导航栏高度会因设备而异,且沉浸式布局下系统栏会覆盖内容区。应动态获取安全区域,示例:

import window from '@ohos.window';

window.getLastWindow(getContext()).then(win => {
  let avoidArea = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);
  let paddingBottom = px2vp(avoidArea.bottomRect.height);
  // 将 paddingBottom 赋值给 Scroll 的 padding 或子项的 margin
});

在组件中通过状态变量绑定该值。若仍不生效,检查 Scroll 是否设置了 .layoutWeight(1) 确保其高度自适应,并确认沉浸式配置时未遗漏 window.setWindowLayoutFullScreen(true) 后的安全区处理。

回到顶部