HarmonyOS 鸿蒙Next中web组件嵌套H5页面,页面可滑动,但调用web组件的scrollTo(0,0)无效

HarmonyOS 鸿蒙Next中web组件嵌套H5页面,页面可滑动,但调用web组件的scrollTo(0,0)无效

web组件嵌套了一个H5页面(H5的代码看不到),页面是可以上下滑动的。想做一个点击状态栏页面回到顶部,先监听状态栏点击事件,然后调用web组件的scrollTo(0,0)回顶,然而没有效果。把scrollTo换成refresh,页面是可以刷新的,说明整体逻辑没问题,应该是web嵌套了H5页面,H5在滚动,但web并没有滚动。请问该如何实现web和H5一起滚动?或者说scrollTo该如何起作用?

监听部分代码:

private subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {
  events: [
    'usual.event.CLICK_STATUSBAR'
  ]
};

public registerPowerSaveModeChange(): void {
  let mSubscriber = commonEventManager.createSubscriberSync(this.subscribeInfo);
  if (mSubscriber === null) {
    console.info(`create subscriber errot!`);
    return;
  }
  commonEventManager.subscribe(mSubscriber,
    async (err: BusinessError, data: commonEventManager.CommonEventData) => {
      if (err) {
        console.info(`Can't handle common event, err: ${err.code}, err: ${err.message}`);
        return;
      }
      // 触发回顶
      this.controller.scrollTo(0, 0, 500);
      console.info('Publish success');
    });
}

aboutToAppear(): void {
  this.registerPowerSaveModeChange()
}

web部分代码:

Web({ src: this.Url, controller: this.controller })
  .backgroundColor(Color.Transparent)
  .height('100%')
  .width('100%')
  .domStorageAccess(true)
  .javaScriptAccess(true)
  .fileAccess(false)
  .darkMode(WindowManager.getInstance().isDarkMode() ? WebDarkMode.On : WebDarkMode.Off)
  .forceDarkAccess(WindowManager.getInstance().isDarkMode() ? true : false)
  .geolocationAccess(false)
  .onProgressChange((event?: ProgressResultObject) => {
    if (event) {
      Logger.d(TAG, 'newProgress: %s', event.newProgress);
      this.progress = event.newProgress;
    }
  })
  .onPageEnd((event?: PageEndCallbackObject) => {
    Logger.i(TAG, 'onPageEnd');
    this.isLoading = false;
  })

更多关于HarmonyOS 鸿蒙Next中web组件嵌套H5页面,页面可滑动,但调用web组件的scrollTo(0,0)无效的实战教程也可以访问 https://www.itying.com/category-93-b0.html

8 回复
import { webview } from '@kit.ArkWeb'
import { webCommonPermissionHelper } from '../common/util/WebCommonPermissionHelper'

@Entry
@Component
struct WebTestPage {
  @State controller: webview.WebviewController = new webview.WebviewController()
  @State url: string | Resource =
    'https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-webview-webviewcontroller'

  build() {
    Scroll() {
      Column() {
        Button('滚动测试').onClick((event: ClickEvent) => {
          this.controller.scrollTo(0, 0, 500);
        })
        Web({
          src: this.url,
          controller: this.controller,
        })
          .layoutWeight(1)
          .width('100%')
          .height('100%')
          .onPermissionRequest((request: OnPermissionRequestEvent) => {
            webCommonPermissionHelper.onWebPermissionRequest(request)
          })
          .onGeolocationShow(async (event: OnGeolocationShowEvent) => {
            AlertDialog.show({ message: JSON.stringify(event, null, 2) })
          })
      }
      // .height('100%')
      .width('100%')
    }
    .height('100%')
    .width('100%')
  }
}

更多关于HarmonyOS 鸿蒙Next中web组件嵌套H5页面,页面可滑动,但调用web组件的scrollTo(0,0)无效的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


楼主好,Web组件内部H5页面的滚动属于WebView独立滚动链,与原生Scroll组件的滚动控制没有联动。

直接调用Web组件的scrollTo仅作用于原生容器层级,无法穿透到H5内部滚动视图!!

你可以通过Web组件控制器执行JavaScript代码控制H5页面内容滚动:

// 修改回顶逻辑触发JS脚本执行

this.controller.runJavaScript('window.scrollTo(0,0);', (error, result) => {

  if (!error) {

    console.info('H5 scrollTo executed');

  }

});

或者通过动态获取H5页面高度实现原生滚动联动也行

Web({ 

  src: this.Url, 

  controller: this.controller 

})

.onPageEnd(e => {

  // 注入JS获取文档高度

  this.controller.runJavaScript(

    'document.documentElement.scrollHeight.toString()', 

    (error, result) => {

      if (!error) {

        this.webHeight = result + 'px'; // 动态设置Web组件高度

      }

    }

  )

})

.height(this.webHeight) // 绑定动态高度

1.通过nestedScroll协调内外滚动层级

Scroll() {
  Web({
    controller: this.webController,
    src: $rawfile('index.html')
  })
  .nestedScroll({ 
    scrollForward: NestedScrollMode.SELF_FIRST, // 先处理Web内部滚动
    scrollBackward: NestedScrollMode.SELF_FIRST
  })
}
.nestedScroll({
  scrollForward: NestedScrollMode.PARENT_FIRST, // Scroll容器处理剩余滚动
  scrollBackward: NestedScrollMode.PARENT_FIRST
})

2.通过JS注入获取H5内容实际高度

Web({
  controller: this.webController,
  src: $rawfile('index.html')
})
.javaScriptOnDocumentStart(`
  window.addEventListener('load', () => {
    const height = document.documentElement.scrollHeight;
    HarmonyOS.postMessage({height: height});
  });
`)
.onMessage((event) => {
  this.webHeight = event.height;
})
.layoutMode(WebLayoutMode.FIT_CONTENT) // 启用自适应布局
  1. 通过JS 进行H5 页面滚动到顶部
this.webController.runJavaScript('window.scrollTo(0,0)')

你还可以通过js来让页面滚动到顶部:

// 调用JavaScript执行页面滚动到顶部
this.webController.runJavaScript('window.scrollTo(0, 0);')
                .then(() => {
                  console.info('Successfully scrolled to top');
                })
                .catch((error: Error) => {
                  console.error('Failed to scroll to top: ' + error.message);
                });
const js = `window.scrollTo({
  top: 0,
  behavior: 'smooth'
});`
this.controller.runJavaScript(js)

建议你现在pc浏览器中调试一下你的网页,调用js代码      ** window.scrollTo(0, 0);**    看看有没有效果吧!

在HarmonyOS鸿蒙Next中,Web组件嵌套H5页面时,调用scrollTo(0,0)无效可能是由于Web组件与H5页面的滚动机制不同步导致的。鸿蒙的Web组件基于系统级实现,而H5页面使用浏览器自身的滚动机制。需要确保在Web组件加载完成后,通过执行JavaScript代码来触发H5页面的滚动重置,例如使用webview.executeJs(“window.scrollTo(0,0)”)。

在HarmonyOS Next中,Web组件的scrollTo方法只能控制Web组件自身的滚动,而无法控制嵌套H5页面的内部滚动。这是因为H5页面有自己的滚动机制,独立于Web组件。

解决方案建议:

  1. 通过JavaScript注入方式控制H5页面滚动:
this.controller.runJavaScript('window.scrollTo(0,0)');
  1. 如果H5页面使用了div等元素滚动,需要获取对应元素:
this.controller.runJavaScript('document.getElementById("scrollContainer").scrollTo(0,0)');
  1. 确保Web组件已加载完成后再执行JS代码,可以在onPageEnd回调中设置标志位。

  2. 如果H5页面是自己开发的,建议在H5页面中监听消息:

// ArkTS侧
this.controller.postMessage('scrollToTop');

// H5侧
window.addEventListener('message', (e) => {
  if(e.data === 'scrollToTop') {
    window.scrollTo(0,0);
  }
});

这种方法能更可靠地控制H5页面内部的滚动行为。

回到顶部