HarmonyOS7 滑动手势:SwipeGesture 检测快速滑动方向

文章目录

    • 前言
    • 效果展示
    • SwipeGesture vs PanGesture
    • 实现原理
      • 滑动方向的判定
      • 角度到方向的转换
    • 代码详解
      • 状态变量
      • 滑动区域
      • SwipeDirection 枚举
      • 完整代码
    • 实际案例
      • 图片轮播翻页
      • 下拉关闭
      • 列表项左滑删除
    • 写在最后

前言

滑动手势(Swipe)和拖拽手势(Pan)看起来很像,但用途完全不同。拖拽是"按住慢慢移",滑动是"快速甩一下"。SwipeGesture 检测的是快速滑动的方向和速度,常用于翻页、切换标签、触发操作等场景。

今天来实现一个四方向滑动检测器,用户在指定区域滑动,界面实时显示滑动方向和次数。

效果展示

页面上方显示滑动方向和计数。下方有一个绿色的滑动区域,用户在里面快速滑动,上方的方向文字就会更新:

  • 向右滑 → “→ 右滑”
  • 向左滑 → “← 左滑”
  • 向上滑 → “↑ 上滑”
  • 向下滑 → “↓ 下滑”

SwipeGesture vs PanGesture

这两个手势的区别一定要搞清楚:

维度SwipeGesturePanGesture
触发条件快速滑动(有速度要求)任意速度的拖动
提供的数据滑动角度实时偏移量
回调频率一次滑动触发一次移动过程中持续触发
适用场景翻页、切换、触发操作拖拽定位、滚动
手指状态快速滑动后立即抬起按住不放慢慢移动

简单说,Swipe 是"甩",Pan 是"拖"

实现原理

滑动方向的判定

SwipeGestureevent.angle返回滑动的角度值(0-360度),我们需要根据角度来判断方向:

0° - 45° / 315° - 360° → 右滑 45° - 135° → 上滑 135° - 225° → 左滑 225° - 315° → 下滑

角度到方向的转换

constangle=event.angle??0if(angle>=45&&angle<135){this.swipeDirection='↑ 上滑'}elseif(angle>=135&&angle<225){this.swipeDirection='← 左滑'}elseif(angle>=225&&angle<315){this.swipeDirection='↓ 下滑'}else{this.swipeDirection='→ 右滑'}

用 if-else 链把角度范围映射到四个方向。

代码详解

状态变量

@StateswipeDirection:string='等待滑动...'@StateswipeCount:number=0

两个状态:当前滑动方向和总滑动次数。

滑动区域

Column(){Column(){Text('←→ 在此区域滑动 ←→').fontSize(14).fontColor('#FFFFFF')}.width('100%').height(120).backgroundColor('#4ECDC4').borderRadius(16).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).gesture(SwipeGesture({direction:SwipeDirection.All}).onAction((event:GestureEvent)=>{this.swipeCount++constangle=event.angle??0if(angle>=45&&angle<135){this.swipeDirection='↑ 上滑'}elseif(angle>=135&&angle<225){this.swipeDirection='← 左滑'}elseif(angle>=225&&angle<315){this.swipeDirection='↓ 下滑'}else{this.swipeDirection='→ 右滑'}}))}.width('100%')

SwipeGesture({ direction: SwipeDirection.All })允许四个方向的滑动。onAction在一次完整的滑动后触发一次(不像 PanGesture 持续触发)。

SwipeDirection 枚举

说明
SwipeDirection.All所有方向
SwipeDirection.Horizontal仅水平(左/右)
SwipeDirection.Vertical仅垂直(上/下)
SwipeDirection.Left仅向左
SwipeDirection.Right仅向右
SwipeDirection.Up仅向上
SwipeDirection.Down仅向下

如果只需要检测左右滑动,用SwipeDirection.Horizontal就行,系统会忽略上下的滑动。

完整代码

@Entry@Componentstruct SwipeGesturePage{@StateswipeDirection:string='等待滑动...'@StateswipeCount:number=0build(){Column(){Column(){Text('滑动手势').fontSize(16).fontWeight(FontWeight.Bold).margin({bottom:16})Column(){Text(this.swipeDirection).fontSize(22).fontWeight(FontWeight.Bold).fontColor('#4D96FF')Text(`滑动次数:${this.swipeCount}`).fontSize(13).fontColor('#999999').margin({top:4})}.width('100%').padding(20).backgroundColor('#F8F8F8').borderRadius(12).alignItems(HorizontalAlign.Center).margin({bottom:20})Column(){Column(){Text('←→ 在此区域滑动 ←→').fontSize(14).fontColor('#FFFFFF')}.width('100%').height(120).backgroundColor('#4ECDC4').borderRadius(16).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).gesture(SwipeGesture({direction:SwipeDirection.All}).onAction((event:GestureEvent)=>{this.swipeCount++constangle=event.angle??0if(angle>=45&&angle<135){this.swipeDirection='↑ 上滑'}elseif(angle>=135&&angle<225){this.swipeDirection='← 左滑'}elseif(angle>=225&&angle<315){this.swipeDirection='↓ 下滑'}else{this.swipeDirection='→ 右滑'}}))}.width('100%')Text('支持上下左右四个方向滑动').fontSize(12).fontColor('#999999').margin({top:12})}.width('100%').padding(24).backgroundColor('#FFFFFF').borderRadius(12)}.width('100%').height('100%').backgroundColor('#F5F6FA').padding(16)}}

实际案例

图片轮播翻页

@StatecurrentIndex:number=0.gesture(SwipeGesture({direction:SwipeDirection.Horizontal}).onAction((event:GestureEvent)=>{constangle=event.angle??0if(angle<90||angle>270){// 右滑 → 上一张if(this.currentIndex>0)this.currentIndex--}else{// 左滑 → 下一张if(this.currentIndex<this.images.length-1)this.currentIndex++}}))

下拉关闭

.gesture(SwipeGesture({direction:SwipeDirection.Down}).onAction(()=>{// 向下滑 → 关闭当前页面router.back()}))

列表项左滑删除

.gesture(SwipeGesture({direction:SwipeDirection.Left}).onAction(()=>{// 显示删除按钮this.showDeleteButton=true}))

写在最后

SwipeGesture是检测"快速滑动"的专用手势。它提供滑动角度,你根据角度判断方向,然后在回调里执行对应的业务逻辑。

PanGesture的区别要记清楚:Swipe 是一次性的方向检测,Pan 是持续的位移追踪。选对工具,交互才能对味。