HarmonyOS7 拖拽方向限制:PanDirection 让组件只能水平或垂直拖动

HarmonyOS7 拖拽方向限制:PanDirection 让组件只能水平或垂直拖动

文章目录

    • 前言
    • 方案对比表
    • 详细实现
      • 水平拖拽
      • 垂直拖拽
    • 完整代码
    • 优劣分析
    • 实际案例
      • 侧滑删除
      • 下拉刷新
    • 写在最后

前言

上篇文章讲了自由拖拽——方块可以往任何方向移动。但实际场景中,很多时候我们需要限制拖拽方向。比如:

  • 音量滑块只能水平拖动
  • 下拉刷新只能垂直拖动
  • 侧滑删除只能水平拖动

PanGesturedirection参数就是用来限制拖拽方向的。

方案对比表

PanDirection提供了以下枚举值:

说明适用场景
All所有方向自由拖拽
Horizontal仅水平滑块、轮播
Vertical仅垂直下拉、列表排序
Left仅向左右滑删除
Right仅向右左滑展开

|Up| 仅向上 | 上滑关闭 |
|Down| 仅向下 | 下拉刷新 |

详细实现

水平拖拽

@StatehOffsetX:number=0@StatehPosX:number=0Stack(){Row(){Column(){Text('← →').fontSize(18).fontColor('#FFFFFF')}.width(70).height(50).backgroundColor('#4D96FF').borderRadius(12).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).offset({x:this.hOffsetX,y:0}).gesture(PanGesture({direction:PanDirection.Horizontal}).onActionUpdate((event:GestureEvent)=>{this.hOffsetX=this.hPosX+event.offsetX}).onActionEnd(()=>{this.hPosX=this.hOffsetX}))}}.width('100%').height(60).backgroundColor('#F8F8F8').borderRadius(10)

关键点:

  • direction: PanDirection.Horizontal— 只响应水平方向的拖拽
  • .offset({ x: this.hOffsetX, y: 0 })— Y 轴固定为 0,只在 X 轴移动
  • onActionUpdate只使用event.offsetX,忽略event.offsetY

用户上下拖动手指时,方块不会有反应——只有左右拖动才会移动。

垂直拖拽

@StatevOffsetY:number=0@StatevPosY:number=0Stack(){Column(){Column(){Text('↑ ↓').fontSize(18).fontColor('#FFFFFF')}.width(70).height(50).backgroundColor('#6BCB77').borderRadius(12).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).offset({x:0,y:this.vOffsetY}).gesture(PanGesture({direction:PanDirection.Vertical}).onActionUpdate((event:GestureEvent)=>{this.vOffsetY=this.vPosY+event.offsetY}).onActionEnd(()=>{this.vPosY=this.vOffsetY}))}}.width('100%').height(60).backgroundColor('#F8F8F8').borderRadius(10)

垂直拖拽跟水平拖拽的写法完全对称——direction改成Vertical.offset()的 X 固定为 0,使用event.offsetY

完整代码

@Entry@Componentstruct PanGestureDirection{@StatehOffsetX:number=0@StatehPosX:number=0@StatevOffsetY:number=0@StatevPosY:number=0build(){Column(){Column(){Text('拖拽方向限制').fontSize(16).fontWeight(FontWeight.Bold).margin({bottom:16})// 水平拖拽Text('水平拖拽(Horizontal)').fontSize(14).fontColor('#666666').margin({bottom:8})Stack(){Row(){Column(){Text('← →').fontSize(18).fontColor('#FFFFFF')}.width(70).height(50).backgroundColor('#4D96FF').borderRadius(12).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).offset({x:this.hOffsetX,y:0}).gesture(PanGesture({direction:PanDirection.Horizontal}).onActionUpdate((event:GestureEvent)=>{this.hOffsetX=this.hPosX+event.offsetX}).onActionEnd(()=>{this.hPosX=this.hOffsetX}))}}.width('100%').height(60).backgroundColor('#F8F8F8').borderRadius(10)// 垂直拖拽Text('垂直拖拽(Vertical)').fontSize(14).fontColor('#666666').margin({bottom:8})Stack(){Column(){Column(){Text('↑ ↓').fontSize(18).fontColor('#FFFFFF')}.width(70).height(50).backgroundColor('#6BCB77').borderRadius(12).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).offset({x:0,y:this.vOffsetY}).gesture(PanGesture({direction:PanDirection.Vertical}).onActionUpdate((event:GestureEvent)=>{this.vOffsetY=this.vPosY+event.offsetY}).onActionEnd(()=>{this.vPosY=this.vOffsetY}))}}.width('100%').height(60).backgroundColor('#F8F8F8').borderRadius(10)}.width('100%').padding(24).backgroundColor('#FFFFFF').borderRadius(12)}.width('100%').height('100%').backgroundColor('#F5F6FA').padding(16)}}

优劣分析

限制方向的优势:

  • 防止误操作——用户无意中的斜向滑动不会干扰目标方向的拖拽
  • 交互语义更清晰——水平就是水平,垂直就是垂直
  • 简化偏移计算——只需要处理一个轴的数据

限制方向的劣势:

  • 系统判断方向需要一定的拖拽距离,可能导致初始响应有延迟
  • 用户手指的实际滑动轨迹很少有绝对水平或垂直的,系统需要做方向判定

实际案例

侧滑删除

.gesture(PanGesture({direction:PanDirection.Left}).onActionUpdate((event:GestureEvent)=>{this.slideOffset=Math.max(-80,event.offsetX)}).onActionEnd(()=>{if(this.slideOffset<-40){this.slideOffset=-80// 展开删除按钮}else{this.slideOffset=0// 收回}}))

下拉刷新

.gesture(PanGesture({direction:PanDirection.Down}).onActionUpdate((event:GestureEvent)=>{this.pullDistance=Math.min(100,event.offsetY)}).onActionEnd(()=>{if(this.pullDistance>60){this.refreshData()}this.pullDistance=0}))

写在最后

PanDirection让拖拽手势变得精确可控。水平拖拽配水平方向的限制,垂直拖拽配垂直方向的限制——方向明确,交互才清晰。

在实际项目中,90% 的拖拽场景都需要限制方向。自由拖拽虽然酷,但大多数时候用户不需要(也不想要)一个可以到处乱拖的组件。