HarmonyOS鸿蒙Next中沉浸式效果避让策略失效该如何解决

HarmonyOS鸿蒙Next中沉浸式效果避让策略失效该如何解决

【问题现象】

在应用中实现沉浸式效果时:

  • 当设置FullScreen属性后,Navigation导航栏不会避让状态栏,而Navigation导航栏使用padding来避让状态栏后,这一设置会影响所有navDestination页面。
  • 当不设置FullScreen属性,需要铺满全屏的页面,不能在时间栏和系统底部导航条区域渲染。

具体效果如下:

点击放大

点击放大

【背景知识】

1. 窗口全屏布局方案

调整布局系统为全屏布局,界面元素延伸到状态栏和导航条区域实现沉浸式效果。当不隐藏避让区时,可通过接口查询状态栏和导航条区域进行可交互元素避让处理,并设置状态栏或导航条的颜色等属性与界面元素匹配。当隐藏避让区时,通过对应接口设置全屏布局即可。

参考链接:窗口全屏布局方案

2. 组件安全区方案

布局系统保持安全区内布局,然后通过接口延伸绘制内容(如背景色,背景图)到状态栏和导航条区域实现沉浸式效果。该方案下,界面元素仅做绘制延伸,无法单独布局到状态栏和导航条区域,针对需要单独布局UI元素到状态栏和导航条区域的场景建议使用窗口全屏布局方案处理。

参考链接:组件安全区方案

3. padding:组件内边距

参考链接:组件尺寸设置

4. @StorageLink

参考链接:应用全局的UI状态

【解决方案】

针对不同场景下的沉浸式效果需求,可以选择设置或不设置FullScreen属性,采用不同的解决方案处理对应的问题。

1. 设置FullScreen

  • 当应用中大多数页面需要全屏渲染时,可以在onWindowStageCreate方法中全局设置windowLayoutFullScreen为true。或者在需要的场景内单独设置windowLayoutFullScreen为true,退出时恢复原值。
  • 代码示例如下:
EntryAbility.ets
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) ?? '');
          // 此处添加以下代码
          let windowClass: window.Window = windowStage.getMainWindowSync(); // 获取应用主窗口
          // 1. 设置窗口全屏
          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));
          });
      return;
    }
    hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.')
  });
}
xxxPage.ets
import { window } from '@kit.ArkUI';

@Entry
@Component
export struct xxxPage {

  // page中使用此方式设置是否开启FullScreen
  setFullScreen(value:boolean) {
    window.getLastWindow(getContext(this)).then(currentWindow => {
        currentWindow.setWindowLayoutFullScreen(value);
    });
  }

  build() {
    Column() {
      ...
    }
    .height('100%')
    .width('100%')
  }
}

在FullScreen模式下,Navigation的TitleBar会被顶部状态栏遮挡,底部Tab组件会被系统导航条遮挡。可以通过设置padding来手动避让,设置padding后子页面也会受到影响,需要更新Navigation根页面中设置的padding才生效,使用AppStorage可以设置此padding值。

效果如下:

点击放大

点击放大

点击放大

代码示例如下:

Index.ets
AppStorage.setOrCreate('safeTop', 0);
AppStorage.setOrCreate('safeBottom', 0);

@Entry
@Component
struct Index {

  [@StorageLink](/user/StorageLink)('safeTop') safeTop:number = 0;
  [@StorageLink](/user/StorageLink)('safeBottom') safeBottom:number = 0;

  build() {
    Navigation() {
        ...
    }
    .height('100%')
    .width('100%')
    .padding({
      top: this.safeTop,
      bottom: this.safeBottom,
    })
  }
}
xxxPage.ets
@Entry
@Component
export struct xxxPage {

  [@StorageLink](/user/StorageLink)('safeTop') safeTop:number = 0;
  [@StorageLink](/user/StorageLink)('safeBottom') safeBottom:number = 0;

  // 其他page中直接修改
  setSafeTop() {
    window.getLastWindow(getContext(this)).then(windowClass => {
        let topType = window.AvoidAreaType.TYPE_SYSTEM
        let statusBarArea = windowClass.getWindowAvoidArea(topType);
        this.safeTop = statusBarArea.topRect.height;
    });
  }

  setSafeTop() {
    window.getLastWindow(getContext(this)).then(windowClass => {
        let bottomType = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR;
        let bottomArea = windowClass.getWindowAvoidArea(bottomType);
        this.safeBottom = bottomArea.bottomRect.height;
    });
  }

  build() {
    Column() {
      ...
    }
  }
}

2. 不设置FullScreen

当应用中大多数页面需要避让系统顶部状态栏和底部导航条时,可以不使用FullScreen模式,使用组件的扩展安全区域方式。当组件布局不需要避让时,可以通过expandSafeArea属性让组件渲染到非安全区。List 组件还可以通过contentStartOffset和contentEndOffset 设置内容顶部和底部的空余高度。

代码示例如下:

Column() {
  List() {
  }
    .contentStartOffset(this.safeArea.top)
    .contentEndOffset(this.safeArea.bottom)
}
  // 设置底部绘制延伸到头部时间栏和底部导航条
  .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])

【总结】

在应用开发中实现沉浸式效果时,需要根据具体需求选择是否设置FullScreen属性。设置FullScreen属性可以实现全屏渲染,但需要手动避让状态栏和导航条。不设置FullScreen属性则通过组件的扩展安全区域方式避让系统栏。了解并灵活运用这两种方式,可以更好地实现应用的沉浸式效果。


更多关于HarmonyOS鸿蒙Next中沉浸式效果避让策略失效该如何解决的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS鸿蒙Next中沉浸式效果避让策略失效该如何解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,沉浸式效果避让策略失效的解决方案如下:

1. 设置FullScreen属性

  • onWindowStageCreate方法中全局设置windowLayoutFullScreentrue,或在需要的场景内单独设置windowLayoutFullScreentrue,退出时恢复原值。
  • 使用AppStorage设置padding值,手动避让状态栏和导航条。

2. 不设置FullScreen属性

  • 使用组件的扩展安全区域方式,通过expandSafeArea属性让组件渲染到非安全区。
  • 对于List组件,使用contentStartOffsetcontentEndOffset设置内容顶部和底部的空余高度。

根据具体需求选择是否设置FullScreen属性,灵活运用这两种方式实现沉浸式效果。

回到顶部