摘要:Web 前端有轮播图(Carousel),Native 系统有侧滑返回(Swipe Back)。当这两个手势撞在一起时,用户就像陷入了"三国杀"战场——想滑图片却退出了应用,想退出应用却滑不动图片。本文深入讲解 ArkWeb 的手势拦截机制。

⚔️ 1. 冲突现场

场景:
我们在 Web 首页放了一个全宽度的图片轮播组件(Swiper.js)。
用户手指放在轮播图上,向右滑动,试图查看上一张图片。

期望结果:图片切换。
实际结果:触发了鸿蒙系统的"侧滑返回"动画,页面直接后退,甚至退出了 App。

这在 Android 和 iOS 上也很常见,但在全面屏手势主导的鸿蒙设备上尤为突出。

🛡️ 2. 机制解析

手势事件的传递是一个"冒泡"过程,但系统级手势往往拥有最高优先级

  1. 手指触摸屏幕边缘区域(Edge Area)。
  2. 系统层捕获 Touch 事件。
  3. 判定为系统返回手势 -> 消费事件 -> 不再传递给 App
  4. 判定非系统手势 -> 传递给 ArkWeb 组件。
  5. ArkWeb 传递给 JS 引擎。

问题出在第 3 步,系统"截胡"了。

🔧 3. 解决方案

我们需要告诉 ArkWeb:“这一块区域归我管,系统你别动”。

3.1 方法一:CSS touch-action (有限有效)

这是最标准的 Web 方案。

.swiper-container {
    touch-action: pan-y; /* 允许垂直滚动,禁止水平维度的浏览器默认行为 */
}

局限性:这只能阻止浏览器的"历史记录后退"行为,无法阻止系统级的侧滑返回手势。因为系统手势在浏览器内核之上。

3.2 方法二:ArkWeb 拦截 (setWebviewTouchCapture)

鸿蒙 ArkWeb 提供了更底层的 API,允许我们在特定时机"霸占"触摸事件。

但这里有个矛盾:如果我们全局拦截了,那用户真的想返回时怎么办?
我们需要按需拦截

策略

  1. 当 JS 检测到触摸开始点位于轮播图区域时,通知 Native 开启拦截。
  2. 当触摸结束时,通知 Native 关闭拦截。

Native 端 (ArkTS)

// GamePlugin.ets
registerProxy() {
    this.controller.registerJavaScriptProxy({
        setTouchCapture: (capture: boolean) => {
            // 注意:此处 API 需根据具体 SDK 版本调整,概念性代码
            // 目前 ArkWeb 尚未完全开放动态设置系统手势屏蔽的同步接口
            // 这种方案通常存在通信延迟,可能来不及拦截
        }
    }, "gestureBridge", ["setTouchCapture"]);
}

尴尬的现实:由于 JS Bridge 的异步性,等 JS 告诉 Native "我要拦截"时,Native 可能已经把事件交给系统处理了。

3.3 方法三:避让设计 (Design Fix) ✅

目前最稳妥的方案其实是设计避让

系统侧滑返回通常只响应屏幕左右边缘 20vp - 40vp 的区域。

优化方案

  1. 内缩布局:给轮播图加上 padding: 0 20px,不要让可滑动区域贴边。
  2. 边缘留白:设计上避免全屏宽度的横向滑动组件。
  3. 视觉引导:在轮播图两侧添加半透明遮罩,暗示用户从中间滑动。
.swiper-container {
    /* 关键:留出系统手势的安全距离 */
    margin: 0 24px; 
    border-radius: 8px;
    overflow: hidden;
}

这样,用户从屏幕边缘滑动时触发系统返回;从屏幕中间(轮播图区域)滑动时触发图片切换。井水不犯河水。

3.4 终极方案:application-wide 配置

如果你的应用是全屏游戏(如我们的 2048),需要完全接管手势,可以在 module.json5 或代码中禁用系统侧滑返回,改用自定义的返回按钮。

EntryAbility.ets 中:

onWindowStageCreate(windowStage: window.WindowStage) {
    windowStage.getMainWindow().then((win) => {
        // 禁用系统侧滑返回手势
        win.setSystemBarEnable([]); // 隐藏导航栏
        // 配合 Web 内的 history.back() 逻辑
    });
}

对于普通应用,不推荐完全禁用系统手势,这会破坏用户习惯。

🎯 4. 总结

手势冲突是混合开发中的"硬骨头"。

  1. 不要试图与系统抢边缘:系统手势优先级最高,且区域判定在 Native 层。
  2. Design over Code:最好的代码是不写代码。通过 UI 设计避开边缘区域,是成本最低且效果最好的方案。
  3. 沉浸式游戏例外:如果是游戏,果断全屏沉浸,禁用系统手势,自己绘制返回按钮。

学会与系统手势"共存",而不是"对抗"。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐