ArkUI 单一手势:点击、长按、拖动各干各的活

举报
蓝瘦的蜕变 发表于 2026/10/16 18:27:47 2026/10/16
【摘要】 今天我们只看三个单一手势:TapGesture、LongPressGesture、PanGesture。 手势最怕混着讲。点击、长按、拖动本来就是三种不同意图,先把它们拆开跑通,后面再谈组合和冲突会轻松很多。 参考文档: https://developer.huawei.com/consumer/cn/doc/harm

ArkUI 单一手势:点击、长按、拖动各干各的活

今天我们只看三个单一手势:TapGesture、LongPressGesture、PanGesture。

手势最怕混着讲。点击、长按、拖动本来就是三种不同意图,先把它们拆开跑通,后面再谈组合和冲突会轻松很多。

参考文档:

  • https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-interaction-development-guide-overview

TapGesture 适合明确点击

TapGesture({ count: 1 })
  .onAction(() => {
    this.tapText = 'TapGesture 已触发:一次点击'
  })

如果只是普通按钮,onClick 已经够用。TapGesture 更适合后面要和双击、长按、拖动放在一起判断的场景。

LongPressGesture 适合二级动作

LongPressGesture({ repeat: false, duration: 600 })
  .onAction(() => {
    this.longPressText = 'LongPressGesture 已触发:长按完成'
  })

长按不要拿来替代普通点击。一般来说,它更适合收藏、进入选择模式、唤起编辑入口这类不那么高频的动作。

PanGesture 适合拖动反馈

PanGesture({ fingers: 1, distance: 5 })
  .onActionUpdate((event: GestureEvent) => {
    this.panX = event.offsetX
    this.panY = event.offsetY
  })

offsetX 和 offsetY 可以直接拿来做轻量位移。这个 Demo 松手后让卡片回到原位,目的只是看清楚拖动反馈,不做列表排序。

你更常在哪些地方用长按?是进入编辑、批量选择,还是显示更多操作?这个选择会影响用户对页面的第一印象。

完整示例代码

文件位置:entry/src/main/ets/pages/arkUI/interaction/ArkUISingleGestureDemo.ets

@Entry
@Component
struct ArkUISingleGestureDemo {
  @State tapText: string = '点一下蓝色卡片'
  @State longPressText: string = '长按绿色卡片'
  @State panText: string = '拖动橙色卡片'
  @State panX: number = 0
  @State panY: number = 0

  private showTip(message: string): void {
    this.getUIContext().getPromptAction().showToast({
      message: message,
      duration: 1200,
      bottom: 120
    })
  }

  @Builder
  sectionTitle(title: string, desc: string) {
    Column({ space: 6 }) {
      Text(title)
        .fontSize(19)
        .fontWeight(FontWeight.Bold)
        .fontColor('#111827')
      Text(desc)
        .fontSize(13)
        .fontColor('#6B7280')
        .lineHeight(20)
    }
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }

  @Builder
  actionCard(title: string, desc: string, color: string) {
    Column({ space: 10 }) {
      Text(title)
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .fontColor('#FFFFFF')
      Text(desc)
        .fontSize(13)
        .fontColor('#E5E7EB')
        .lineHeight(20)
    }
    .width('100%')
    .padding(16)
    .borderRadius(14)
    .backgroundColor(color)
    .alignItems(HorizontalAlign.Start)
  }

  build() {
    Scroll() {
      Column({ space: 22 }) {
        Column({ space: 8 }) {
          Text('ArkUI 单一手势')
            .fontSize(28)
            .fontWeight(FontWeight.Bold)
            .fontColor('#111827')
          Text('点击、长按、拖动各干各的活')
            .fontSize(16)
            .fontColor('#4B5563')
          Text('单一手势适合先把动作拆清楚。点击负责确认,长按负责二级动作,拖动负责位置变化。')
            .fontSize(14)
            .fontColor('#6B7280')
            .lineHeight(22)
        }
        .width('100%')
        .alignItems(HorizontalAlign.Start)

        this.sectionTitle('TapGesture:明确的一次点击', '点击手势比 onClick 更适合和其它手势组合。')
        Column() {
          this.actionCard('TapGesture', '点一下这张卡片。', '#2563EB')
          Text(this.tapText)
            .fontSize(13)
            .fontColor('#FFFFFF')
            .lineHeight(20)
            .padding(10)
            .borderRadius(10)
            .backgroundColor('#00000033')
            .width('100%')
        }
        .width('100%')
        .gesture(
          TapGesture({ count: 1 })
            .onAction(() => {
              this.tapText = 'TapGesture 已触发:一次点击'
              this.showTip('点击手势触发')
            })
        )

        this.sectionTitle('LongPressGesture:不要拿来替代普通点击', '长按适合收藏、选择、进入编辑这类二级动作。')
        Column() {
          this.actionCard('LongPressGesture', '按住一小会再松开。', '#0F766E')
          Text(this.longPressText)
            .fontSize(13)
            .fontColor('#FFFFFF')
            .lineHeight(20)
            .padding(10)
            .borderRadius(10)
            .backgroundColor('#00000033')
            .width('100%')
        }
        .width('100%')
        .gesture(
          LongPressGesture({ repeat: false, duration: 600 })
            .onAction(() => {
              this.longPressText = 'LongPressGesture 已触发:长按完成'
              this.showTip('长按手势触发')
            })
        )

        this.sectionTitle('PanGesture:拖动就让位置跟着变', 'PanGesture 的 offsetX、offsetY 可以拿来做轻量拖动反馈。')
        Column() {
          this.actionCard('PanGesture', '按住并拖动卡片,松手后回到原位。', '#C2410C')
          Text(this.panText)
            .fontSize(13)
            .fontColor('#FFFFFF')
            .lineHeight(20)
            .padding(10)
            .borderRadius(10)
            .backgroundColor('#00000033')
            .width('100%')
        }
        .width('100%')
        .translate({ x: this.panX, y: this.panY })
        .gesture(
          PanGesture({ fingers: 1, distance: 5 })
            .onActionUpdate((event: GestureEvent) => {
              this.panX = event.offsetX
              this.panY = event.offsetY
              this.panText = `拖动中:x ${Math.round(event.offsetX)}, y ${Math.round(event.offsetY)}`
            })
            .onActionEnd(() => {
              this.panX = 0
              this.panY = 0
              this.panText = '拖动结束:卡片回到原位'
              this.showTip('拖动结束')
            })
        )
      }
      .width('100%')
      .padding(24)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F8FAFC')
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。