HarmonyOS鸿蒙Next中如何解决Web组件在嵌套如Scroll组件后,无法跟随页面整体滑动的问题

HarmonyOS鸿蒙Next中如何解决Web组件在嵌套如Scroll组件后,无法跟随页面整体滑动的问题

【问题现象】

在Scroll组件内嵌套使用Web组件和其他容器组件的组合时,如下:

Scroll() {
  Row() {}
  Web() {}
  Row() {}
  List() {}
}

Web组件显示不全或只能单独滚动,无法实现与Row、List等组件连为一个整体进行滚动。

【背景知识】

Web组件:

Web组件提供网页显示功能。

事件:

  • onPageEnd:在页面加载完成时触发的回调,可以添加设置页面加载完成后的操作。
  • runJavaScript:返回JavaScript脚本执行的结果,需要放在页面加载完成后,如onPageEnd。
  • onFirstMeaningfulPaint:页面渲染完成时触发的回调,用法与onPageEnd类似。
  • onGestureJudgeBegin:自定义手势判定,当绑定的手势被接受时触发自定义内容的回调。

属性:

layoutMode:用来设置Web的布局模式,包含两种:Web布局跟随系统(WebLayoutMode.NONE)和Web组件高度基于前端页面高度的自适应网页布局(WebLayoutMode.FIT_CONTENT)。

【定位思路】

从问题现象可以看出当前有两种状态:Web组件会单独滑动以及内容显示不全。

分析两种状态的原因:

  1. Web组件单独滑动是因为固定了组件的高度,且该高度小于内容高度;
  2. Web组件内容显示不全是因为在第1点的基础上禁止了Web的滑动。

所以问题的关键就在于如何控制Web组件的高度,让其可以适应内容,从而达到将Web变成一个完全展开的view。

【解决方案】

方法一:手动计算高度

在HTML文件中完成高度计算(watchWindowSize函数)。

<!DOCTYPE html>
<html>
<body>
<p>
    <h1>测试测试</h1>
    <h2>测试测试</h2>
    <h2>测试测试</h2>
</p>
</body>
<script type="text/javascript">
    function watchWindowSize() { 
        var h = document.body.clientHeight; 
        return h; 
    }
</script>
</html>

然后通过runJavaScript将获取到的高度传入ArkTS页面中,并在onPageEnd回调中接收并设置webview的高度。

Web({ src: $rawfile('index.html'), controller: this.webviewController })
  .javaScriptAccess(true) // 设置是否允许执行js脚本,默认为true
  .onPageEnd(e => {
    this.webviewController.runJavaScript( // 执行js脚本
      'watchWindowSize()', (error, result) => {
      this.webResult = result; // 获取js监听html返回的值
    }
    );
  })

优化:考虑到onPageEnd是页面加载完回调,非页面渲染完成,这样可能会导致前后获取的高度不一致,可以用onFirstMeaningfulPaint替换onPageEnd在页面渲染完成时进行高度计算,不需要再监听HTML文件,同时加上对Web的系统手势进行限制,从而实现整体滑动。

Web({ src: $rawfile('index.html'), controller: this.webviewController })
  .height(this.realHeight > 0 ? this.realHeight : 'auto') // 执行onFirstMeaningfulPaint回调获取组件高度,
  .onFirstMeaningfulPaint(e => {
    this.pageHeight = this.webviewController.getPageHeight();
    this.realHeight = px2vp(this.pageHeight) // 单位转换
  }) 
   // 禁用Web的系统手势
  .onGestureJudgeBegin((gestureInfo: GestureInfo, event: BaseGestureEvent) => {
    if (gestureInfo.isSystemGesture) {
      return GestureJudgeResult.REJECT
    } else {
      return GestureJudgeResult.CONTINUE
    }
  })

方法二:Web自适应

通过设置layoutMode属性为WebLayoutMode.FIT_CONTENT让Web完成自适应内容高度。

// 网页内容过宽或者过长时需要制定设置为RenderMode.SYNC_RENDER
Web({ src: $rawfile('index.html'), controller: this.webviewController, renderMode: RenderMode.SYNC_RENDER })
  .width('100%')
  .height('100%')
  .layoutMode(WebLayoutMode.FIT_CONTENT) // 设置web组件高度给予前端页面高度进行自适应
  .overScrollMode(OverScrollMode.NEVER) // 关闭过界回弹效果
  .zoomAccess(false) // 关闭手势缩放

运行代码可以发现已经实现了Web组件跟随其他组件一起整体滑动:

图片1 图片2 图片3

【总结】

方法一较贴近底层实现,用最简单直接的方式获取页面高度并赋值给Web组件,容易想到但代码量偏多且复杂度高,出错率高;

相比之下方法二则更简单实用,同时支持页面变化(点击进入新的页面),不支持瀑布流网页(下拉到底部加载更多)。


更多关于HarmonyOS鸿蒙Next中如何解决Web组件在嵌套如Scroll组件后,无法跟随页面整体滑动的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS鸿蒙Next中如何解决Web组件在嵌套如Scroll组件后,无法跟随页面整体滑动的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,Web组件嵌套在Scroll组件后无法跟随页面整体滑动的问题可以通过以下两种方法解决:

方法一:手动计算高度

  1. 在HTML文件中使用watchWindowSize函数计算页面高度。
  2. 通过runJavaScript将高度传入ArkTS页面,并在onFirstMeaningfulPaint回调中设置Web组件高度。
  3. 禁用Web的系统手势,确保整体滑动。

方法二:Web自适应

  1. 设置Web组件的layoutMode属性为WebLayoutMode.FIT_CONTENT,使Web组件高度自适应前端页面高度。
  2. 关闭过界回弹效果和手势缩放,确保Web组件与其他组件一起整体滑动。

方法一代码量较多且复杂,方法二更简单实用,但不支持瀑布流网页。

回到顶部