HarmonyOS 鸿蒙Next中求沉浸光感tab嵌套web的沉浸式模式安全区扩展适配方法

HarmonyOS 鸿蒙Next中求沉浸光感tab嵌套web的沉浸式模式安全区扩展适配方法 如图,尝试做了一个demo,发现始终解决不了底下的黑块,有没有大佬讲解一下怎么操作感谢🙏🙏

图片


更多关于HarmonyOS 鸿蒙Next中求沉浸光感tab嵌套web的沉浸式模式安全区扩展适配方法的实战教程也可以访问 https://www.itying.com/category-93-b0.html

7 回复

这个问题课可以查看窗口沉浸,我建议使用setWindowLayoutFullScreen()来实现应用全屏,并且弃用ignoreLayoutSafeArea()expandSafeArea,这两个使用起来再多层组件嵌套的时候很容易混乱,不容易理清。可以查看以下代码:

onWindowStageCreate(windowStage: window.WindowStage) {
    // Main window is created, set main page for this ability
    Logger.info(TAG, 'Ability onWindowStageCreate');

    windowStage.loadContent('pages/Index', (err, data) => {
      if (err.code) {
        Logger.error(TAG, `Failed to load the content. Cause: ${JSON.stringify(err) ?? ''}`);
        return;
      }
      Logger.info(TAG, `Succeeded in loading the content. Data: ${JSON.stringify(data) ?? ''}`);
    });

    try {
      windowStage.getMainWindow((err, data) => {
        if (err.code) {
          Logger.error(TAG, `getMainWindow failed, code=${err.code}, msg=${err.message}`);
          return;
        }
        data.setWindowLayoutFullScreen(true).then(() => {
          Logger.info(TAG, `Succeeded to change full-screen state: ${true}.`);
        }).catch((err: Error) => {
          Logger.error(TAG, `Failed to change full-screen state. Cause message: ${JSON.stringify(err)}`);
        });
        data.setWindowBackgroundColor(Constants.BACKGROUND_COLOR)
      })
    } catch (error) {
      Logger.error(TAG, `Ability onWindowStageCreate, error=${JSON.stringify(error)}`);
    }
  }

应用设置全屏后,所有界面都会延伸到状态栏和导航栏,使窗口沉浸,如果想规避的话可以手动在顶部和底部添加空白组件,设置topRect和bottomRect,获取逻辑如下:

  /**
   * 初始化窗口属性
   * 获取窗口的初始尺寸、安全区信息等
   * 注意:断点由媒体查询系统统一管理,此处不设置断点
   * @param windowClass 窗口实例
   */
  private initializeWindowProperties(): void {
    const windowClass = this.mainWindowClass
    try {
      // 获取系统状态栏避让区域
      const systemAvoidArea = windowClass!.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
      this.windowProperties.topRectPx = systemAvoidArea.topRect.height
      this.windowProperties.topRect = this.uiContext!.px2vp(systemAvoidArea.topRect.height);
      Logger.info(TAG, `顶部安全区高度: ${this.windowProperties.topRectPx}px`);
      Logger.info(TAG, `顶部安全区高度: ${this.windowProperties.topRect}vp`);

      // 获取导航栏避让区域
      const navAvoidArea = windowClass!.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);
      this.windowProperties.bottomRectPx = navAvoidArea.bottomRect.height
      this.windowProperties.bottomRect = this.uiContext!.px2vp(navAvoidArea.bottomRect.height);
      Logger.info(TAG, `底部安全区高度: ${this.windowProperties.bottomRectPx}px`);
      Logger.info(TAG, `底部安全区高度: ${this.windowProperties.bottomRect}vp`);

      // 获取窗口尺寸
      const windowSize = windowClass!.getWindowProperties().windowRect;
      this.windowProperties.winWidthPx = windowSize.width
      this.windowProperties.winHeightPx = windowSize.height
      this.windowProperties.winWidth = this.uiContext!.px2vp(windowSize.width);
      this.windowProperties.winHeight = this.uiContext!.px2vp(windowSize.height);
      Logger.info(TAG, `窗口尺寸: ${this.windowProperties.winWidth}x${this.windowProperties.winHeight}vp`);
      Logger.info(TAG, `窗口尺寸: ${this.windowProperties.winWidthPx}x${this.windowProperties.winHeightPx}px`);

      // 获取窗口装饰高度(如果支持)
      if (canIUse('SystemCapability.Window.SessionManager')) {
        const height = windowClass!.getWindowDecorHeight();
        this.windowProperties.decorHeightPx = height
        this.windowProperties.decorHeight = this.uiContext!.px2vp(height);
        Logger.info(TAG, `窗口装饰高度: ${this.windowProperties.decorHeight}vp`);
        Logger.info(TAG, `窗口装饰高度: ${this.windowProperties.decorHeightPx}px`);
      }
    } catch (error) {
      Logger.error(TAG, `初始化窗口属性失败: ${error.message}`);
    }
  }

获取避让高度后可以在UI中使用AppStorage使用。

更多关于HarmonyOS 鸿蒙Next中求沉浸光感tab嵌套web的沉浸式模式安全区扩展适配方法的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


黑块是因为你系统是深色模式,调成浅色模式,底部就是白色遮罩了

其实应该是可以用主题色来控制的,但是要看你的代码支不支持

WithTheme({ colorMode: ThemeColorMode.LIGHT })

cke_3959.jpeg

在你的UIAbility中的生命周期onWindowStageCreate中设置应用浸式的效果就可以啦,

onWindowStageCreate(windowStage: window.WindowStage): void {
    // 设置应用全屏沉浸式
    windowStage.getMainWindow((err: BusinessError, data: window.Window) => {
      data.setWindowLayoutFullScreen(true)
    })
    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.');
    });
  }

学习了

HarmonyOS 鸿蒙Next中实现沉浸光感tab嵌套Web的沉浸式模式,需通过WindowStagesetWindowLayoutFullScreen(true)启用全屏布局,并调用SystemBarConfig获取状态栏、导航栏区域。在Web组件外层容器设置expandSafeArea属性为[SafeAreaType.SYSTEM]或对应边,同时监听onAreaChange事件动态调整Web内容边距,确保不被系统栏遮挡。

关于HarmonyOS NEXT中沉浸光感Tab嵌套WebView底部黑块的问题

这是典型的WebView安全区适配未同步所致。根本原因在于WebView默认不感知系统导航栏的避让区域,导致其渲染内容超出安全区,从而在底部显示为黑色或半透明色块。

解决方案核心:通过setSpecificResizeListener监听安全区变化,并动态注入CSS/JS到WebView内容中。

具体适配方法:

  1. 设置WebView的布局参数为沉浸式
    在XML布局中将WebView的layout_height设为match_parent,同时通过setSystemBarAvoid(true)让WebView避开系统状态栏/导航栏,但此时WebView内HTML可能仍会留白或出现黑块。

  2. 监听安全区变化并注入适配样式
    在Ability或Page中,通过getWindow().setSpecificResizeListener监听窗口安全区变化。当触发回调时,获取safeAreaInsetsbottom值(导航栏高度),然后调用WebView的evaluateJavascript方法向页面注入CSS变量:

    // 注入CSS: 利用env(safe-area-inset-bottom)适配iOS;鸿蒙无此环境变量,需直接设置
    document.documentElement.style.setProperty('--safe-area-inset-bottom', bottom + 'px');
    

    然后在Web页面的CSS中,将底部固定定位元素的bottom设置为var(--safe-area-inset-bottom)

  3. 若WebView内部是第三方页面
    无法修改页面CSS时,需通过evaluateJavascript动态修改WebView的滚动容器或body的padding-bottom。示例注入JS如下:

    var style = document.createElement('style');
    style.innerHTML = 'body { padding-bottom: ' + bottom + 'px !important; }';
    document.head.appendChild(style);
    
  4. 关键注意事项

    • 必须在onPageFinished或页面加载完成后才能注入上述JS,否则注入无效。
    • 屏幕旋转或导航栏手势切换时,需重新监听安全区变化并再次注入。
    • 若Tab与WebView同层渲染,确保Tab组件的避让区已正确处理(通常Tab组件自带适配)。

常见误避坑:

  • 仅设置setSystemBarAvoid(true)不够,因为WebView不执行鸿蒙安全区布局回调。
  • 在WebView的onLayout中直接获取的bottom值可能为0,务必通过setSpecificResizeListener回调获取。

通过上述方法,黑块应消失,WebView内容将顶满至导航栏边缘。若仍有黑块,检查注入时机是否过晚,或确认WebView未设置多余的Padding/Margin。

回到顶部