HarmonyOS 鸿蒙Next 如何解决Web组件高度无法动态改变的问题

发布于 1周前 作者 yuanlaile 最后一次编辑是 5天前 来自 鸿蒙OS

【问题现象】

在Web组件中,加载了一个包含输入区域的HTML页面,当点击页面中的任何区域,系统输入法弹出之后会通过listenKeyboard监听到输入法键盘高度,并压缩Web组件的高度,让它缩小到屏幕上半部分。

  • **预期效果:**系统输入法弹出后,Web组件的渲染区域缩小到屏幕上半部分,并且在Web组件和输入法之间有预留的动态避让区(通过Blank组件实现)。
  • **实际效果:**系统输入法弹出后,虽然组件树中感知到动态避让区(Blank组件)高度为413vp,但实际并没有绘制出动态避让区,且Web组件的渲染区域并未缩小到屏幕上半部分,如下图。

点击放大

在下面代码片段中,期望通过监听键盘高度来实现Web组件高度动态改变。

问题代码如下:

import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
import { window } from '@kit.ArkUI';

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();
  @State toolOff: number = 0;

  aboutToAppear(): void {
    try {
      webview.WebviewController.setWebDebuggingAccess(true);
      this.listenKeyboard();
    } catch (error) {
      console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
    }
  }

  //监听键盘高度
  private listenKeyboard() {
    window.getLastWindow(getContext(this)).then(currentWindow => {
      //监听键盘高度,处理工具条偏移量
      currentWindow.on('keyboardHeightChange', (data) => {
        let keyboardHeight = Math.floor(px2vp(data));
        if (keyboardHeight > 0) {
          //键盘编辑态,偏移量 = 键盘高度
          this.toolOff = keyboardHeight + 100
        } else {
          //无键盘编辑态,安全区高度
          this.toolOff = 0
        }
      })
    })
  }

  build() {
    Stack() {
      Column() {
        Web({ src: $rawfile('index.html'), controller: this.controller })
          .onControllerAttached(() => {
            // 推荐在此loadUrl、设置自定义用户代理、注入JS对象等
            console.log('onControllerAttached excute')
          }).layoutWeight(1)

        //编辑态避让区
        Blank()
          .backgroundColor("00000000")
          .width('100%')
          .height(this.toolOff)
      }
    }
  }
}

【背景知识】

  • 使用Web组件加载页面:页面加载是Web组件的基本功能。根据页面加载数据来源可以分为三种常用场景,包括加载网络页面、加载本地页面、加载HTML格式的富文本数据。
  • Web组件大小自适应页面内容布局:使用Web组件大小自适应页面内容布局模式时,能使Web组件的大小根据页面内容自适应变化。
  • 安全区域:安全区域是指页面的显示区域,默认不与系统设置的非安全区域比如状态栏、导航栏区域重叠,默认情况下开发者开发的界面都被布局在安全区域内。

【定位思路】

为解决Web组件高度无法改变的问题,可以从组件渲染效果以及安全区域限制方面考虑:

  • 排查Blank组件在高度动态修改时的作用

如果Blank组件高度动态修改后只是覆盖上去了,并不是把Web页面顶上去,那么Web页面高度没有变化,导致看到手机上效果和inspector上效果不一致。虽然修改height(‘calc(100% - 413vp)’)后可以达到理想效果,但是Web组件的高度并不能动态改变。

  • 排查是否只是改变Web组件在屏幕上的显示区域

在Web组件上加一个layoutWeight(1)属性后,虽然会改变当前Web组件在屏幕上的显示区域,但它的高度是不会发生改变的。由于inspector是通过获取组件高度来绘制的,因此layoutWeight(1)属性没办法修改Web组件的高度,只能修改其在父组件中的布局。可以看到inspector上的Web高度始终没有改变,它的显示区域只是被盖上,并不会动态改变。

  • 针对安全区域进行处理

通过排查可以知道,问题代码的处理,并不能使Web组件的高度动态变化。参考背景知识,为了解决这个问题,需要通过突破安全区域的限制来处理。利用安全区域的expandSafeArea属性支持组件不改变布局情况下扩展其绘制区域至安全区外。

【解决方案】

根据定位思路,在web中添加expandSafeArea([SafeAreaType.KEYBOARD]),控制组件扩展其安全区域。处理效果如下图,可以看到在键盘上方按照预期成功产生了空白的预留区域,实现了Web组件的高度动态变化。

Web({ src: $rawfile('index.html'), controller: this.controller })
  .onControllerAttached(() => {
    // 推荐在此loadUrl、设置自定义用户代理、注入JS对象等
    console.log('onControllerAttached excute')
  }).layoutWeight(1)
  .expandSafeArea([SafeAreaType.KEYBOARD])

处理效果:

点击放大

【总结】

对于组件在页面显示区域内的变化,可以考虑设置组件绘制内容突破安全区域的限制来处理。其中需要注意的几点是:

(1)组件设置expandSafeArea属性之后生效的条件为:

  • type为SafeAreaType.KEYBOARD时默认生效,组件不避让键盘。
  • 设置其他type,组件的边界与安全区域重合时组件能够延伸到安全区域下。例如:设备顶部状态栏高度100,那么组件在屏幕中的绝对位置需要为0 <= y <= 100。

(2)组件延伸到安全区域下,在安全区域处的事件,如点击事件等可能会被系统拦截,优先给状态栏等系统组件响应。

(3)滚动类容器内的组件不建议设置expandSafeArea属性,如果设置,需要按照组件嵌套关系,将当前节点到滚动类祖先容器间所有直接节点设置expandSafeArea属性,否则expandSafeArea属性在滚动后可能会失效。

(4)除了组件扩展其安全区域外,和键盘相关比较常见的还有setKeyboardAvoidMode - 控制虚拟键盘抬起时页面的避让模式getKeyboardAvoidMode - 返回虚拟键盘抬起时的页面避让模式。

更多示例请见官方文档安全区域

1 回复

针对HarmonyOS 鸿蒙Next中Web组件高度无法动态改变的问题,可以尝试以下解决方案:

  1. 设置layoutMode:确保Web组件使用了layoutMode(WebLayoutMode.FIT_CONTENT),这能使Web组件的大小根据页面内容自适应变化。
  2. 使用nestedScroll属性:在Scroll组件中嵌套Web组件时,应设置nestedScroll属性,并合理配置其滚动行为(如scrollForwardscrollBackward),以支持嵌套滚动。
  3. JavaScript注入:通过javaScriptOnDocumentStart注入JavaScript,确保在页面加载完成后执行相关代码,如动态调整Web组件的尺寸。
  4. 明确宽度设置:宽度设置不明确可能导致Scroll组件的高度无法正确计算,因此需要确保Web组件有明确的宽度设置。
  5. 检查Web内容:确保加载的HTML内容没有额外的空白区域或未正确关闭的标签,这些都会影响Web组件的高度计算。

此外,如果Web组件加载的是外部网页,还需确保网页已适配鸿蒙系统的用户代理(UA),可通过setCustomUserAgent方法设置合适的UA字符串。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部