文章目录
- 前言
- 效果展示
- SwipeGesture vs PanGesture
- 实现原理
- 滑动方向的判定
- 角度到方向的转换
- 代码详解
- 状态变量
- 滑动区域
- SwipeDirection 枚举
- 完整代码
- 实际案例
- 图片轮播翻页
- 下拉关闭
- 列表项左滑删除
- 写在最后
前言
滑动手势(Swipe)和拖拽手势(Pan)看起来很像,但用途完全不同。拖拽是"按住慢慢移",滑动是"快速甩一下"。SwipeGesture 检测的是快速滑动的方向和速度,常用于翻页、切换标签、触发操作等场景。
今天来实现一个四方向滑动检测器,用户在指定区域滑动,界面实时显示滑动方向和次数。
效果展示
页面上方显示滑动方向和计数。下方有一个绿色的滑动区域,用户在里面快速滑动,上方的方向文字就会更新:
- 向右滑 → “→ 右滑”
- 向左滑 → “← 左滑”
- 向上滑 → “↑ 上滑”
- 向下滑 → “↓ 下滑”
SwipeGesture vs PanGesture
这两个手势的区别一定要搞清楚:
| 维度 | SwipeGesture | PanGesture |
|---|---|---|
| 触发条件 | 快速滑动(有速度要求) | 任意速度的拖动 |
| 提供的数据 | 滑动角度 | 实时偏移量 |
| 回调频率 | 一次滑动触发一次 | 移动过程中持续触发 |
| 适用场景 | 翻页、切换、触发操作 | 拖拽定位、滚动 |
| 手指状态 | 快速滑动后立即抬起 | 按住不放慢慢移动 |
简单说,Swipe 是"甩",Pan 是"拖"。
实现原理
滑动方向的判定
SwipeGesture的event.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 是持续的位移追踪。选对工具,交互才能对味。