HarmonyOS鸿蒙Next中Web组件阻止了Swiper的左右滑动

HarmonyOS鸿蒙Next中Web组件阻止了Swiper的左右滑动 问题如上所述,当Swiper中套用了很多Scroll、Tabs、List等组件,然后再到绘制Web组件;

会导致Web组件中左右滑动时,不会触发Swiper的滑动事件;

在Web组件设置下面代码,可以解决,但是Web组件中的点击事件就不再响应了;

.hitTestBehavior(HitTestMode.None) // 使预览Web不响应手势

有什么好的解决办法~

虽然Web组件有nestedScroll属性控制左右滑动,但是上层的List组件和Scroll组件的nestedScroll属性不能控制左右滑动,所以这种办法暂时不可行;

        .nestedScroll({
          scrollUp: NestedScrollMode.SELF_FIRST,
          scrollDown: NestedScrollMode.PARENT_FIRST,
          scrollLeft: NestedScrollMode.PARENT_FIRST,
          scrollRight: NestedScrollMode.PARENT_FIRST,
        })


更多关于HarmonyOS鸿蒙Next中Web组件阻止了Swiper的左右滑动的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

感觉正常情况,web组件是不会影响swiper滑动的

import { webview } from '@kit.ArkWeb';
import { ZTQJavaScriptProxy } from './ZTQJavaScriptProxy';

@Entry
@Component
export struct Index {
  private swiperController: SwiperController = new SwiperController()
  controller: webview.WebviewController = new webview.WebviewController();
  private javaScriptProxy: ZTQJavaScriptProxy = new ZTQJavaScriptProxy()

  build() {
    Column() {
      Swiper(this.swiperController) {
        ForEach([0, 1, 2, 3, 4], (item: number) => {
          Column() {
            Text(item.toString()).height(300).backgroundColor('#C0C0C0')
            if (item == 2) {
              Web({ src: $rawfile('proxy.html'), controller: this.controller })
                .width('100%')
                .layoutMode(1)
                .keyboardAvoidMode(WebKeyboardAvoidMode.RESIZE_VISUAL)
                // .nestedScroll({
                //   scrollUp: NestedScrollMode.SELF_FIRST,
                //   scrollDown: NestedScrollMode.PARENT_FIRST,
                //   scrollLeft: NestedScrollMode.PARALLEL,
                //   scrollRight: NestedScrollMode.PARALLEL,
                // })
                // .hitTestBehavior(HitTestMode.None) // 使预览Web不响应手势
                .overScrollMode(OverScrollMode.NEVER)
                .javaScriptAccess(true)
                .domStorageAccess(true)
                .zoomAccess(false)
                .textZoomRatio(100)
                .onControllerAttached(() => {
                  this.javaScriptProxy.setContainer(this)
                })
                .javaScriptProxy({
                  object: this.javaScriptProxy,
                  name: 'MyWebView',
                  methodList: ['showToast'],
                  controller: this.controller
                })
            }
          }.width('100%').height('100%')
        }, (item: number) => JSON.stringify(item))
      }
      .width('100%')
      .padding({ left: 20, right: 20 })
      .autoPlay(false) //自动播放
      .loop(false) //是否循环播放
      .indicator(false) //不展示导航点
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#ff00')
    .linearGradient({
      // 渐变方向
      direction: GradientDirection.Bottom,
      // 渐变颜色
      colors: [['#857', 0.0], [Color.White, 1]]
    })
  }
}

更多关于HarmonyOS鸿蒙Next中Web组件阻止了Swiper的左右滑动的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,Web组件默认会拦截触摸事件,导致Swiper组件无法正常左右滑动。可通过在Web组件上设置onTouch事件监听并调用event.stopPropagation()来阻止事件冒泡,或调整布局避免事件冲突。需确保Web组件不独占触摸事件传递路径。

这是一个典型的嵌套滚动冲突问题。Web组件默认会拦截所有手势事件,导致外层Swiper无法接收到滑动事件。

核心解决方案是使用onInterceptKeyEventonTouch事件监听,配合条件判断来手动控制事件传递。

以下是具体实现方案:

  1. 为Web组件添加触摸事件监听
Web({ src: 'https://example.com' })
  .onTouch((event: TouchEvent) => {
    if (event.type === TouchType.Move) {
      // 判断是否为水平滑动
      const deltaX = Math.abs(event.touches[0].x - event.touches[0].screenX);
      const deltaY = Math.abs(event.touches[0].y - event.touches[0].screenY);
      
      // 如果主要是水平滑动,且Web内容已滚动到边界,则允许事件冒泡
      if (deltaX > deltaY && this.isWebAtHorizontalBoundary()) {
        return true; // 允许事件继续传递
      }
      return false; // Web组件消费事件
    }
    return true;
  })
  1. 结合hitTestBehavior的改进用法
.hitTestBehavior(HitTestMode.Transparent)

使用Transparent而不是None,这样Web组件仍然可以接收点击事件,但手势事件可以穿透。

  1. 使用gesture事件更精确控制
.gesture(
  PanGesture({ direction: PanDirection.Horizontal })
    .onActionStart(() => {
      // 记录起始状态
    })
    .onActionUpdate((event: GestureEvent) => {
      // 根据Web内容滚动状态决定是否传递事件
      if (this.shouldPassToSwiper(event)) {
        // 手动触发Swiper滑动
      }
    })
)
  1. 考虑使用WebController监听滚动边界
const webController = new WebController();

Web({ src: 'https://example.com', controller: webController })
  .onScroll(() => {
    // 监听Web内部滚动位置
    webController.getHitTestValue().then((value) => {
      this.isAtEdge = value;
    });
  })

关键点

  • 需要判断Web内容是否已滚动到左右边界
  • 在边界状态下,水平滑动事件应传递给父级Swiper
  • 垂直滑动事件通常由Web组件自身处理
  • 点击事件需要保持正常响应

这种方案既保持了Web组件的正常交互,又解决了与Swiper的手势冲突。

回到顶部