文章目录
- 前言
- 基础概念
- onClick vs gesture(TapGesture)
- onClick 的触发条件
- 从简到繁
- 最简单的点击
- 记录点击时间
- 显示点击信息
- 完整代码
- 常见问题
- Q:任何组件都能加 onClick 吗?
- Q:onClick 和 onTouch 有什么区别?
- Q:双击怎么实现?
- 进阶技巧
- 点击反馈效果
- 防重复点击
- 写在最后
前言
手势是移动端交互的灵魂。没有手势的界面就是一张静态图。ArkUI 提供了丰富的手势 API,其中最基础的就是点击手势——onClick。
别看onClick简单,它是一切手势交互的起点。按钮点击、列表项点击、卡片点击、图片点击……到处都是它。今天从基础开始,把点击手势讲透。
基础概念
onClick vs gesture(TapGesture)
ArkUI 里有两种方式处理点击:
| 方式 | 写法 | 特点 |
|---|---|---|
onClick | .onClick(() => {...}) | 简单直接,适合大多数场景 |
TapGesture | .gesture(TapGesture().onAction(() => {...})) | 可设置点击次数、与其他手势组合 |
对于单纯的点击响应,onClick就够用了。TapGesture的优势在于可以设置count(双击、三击)和跟其他手势并行识别。
onClick 的触发条件
onClick在用户完成一次"按下 + 抬起"操作后触发。注意是"完成"——如果用户按下去之后滑走了(滑出组件区域),onClick不会触发。这个行为跟 HTML 的click事件一致。
从简到繁
最简单的点击
@StatetapCount:number=0Column(){Text('点击区域').fontSize(16).fontColor('#FFFFFF')}.width('100%').height(120).backgroundColor('#4D96FF').borderRadius(16).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).onClick(()=>{this.tapCount++})给一个Column容器加上.onClick,整个区域就变成可点击的了。每次点击,计数器 +1。
记录点击时间
@StatetapCount:number=0@StatelastTapTime:string=''.onClick(()=>{this.tapCount++this.lastTapTime=newDate().toLocaleTimeString()})在计数器之外,再记录上次点击的时间。toLocaleTimeString()返回类似 “14:30:25” 格式的本地时间字符串。
显示点击信息
Text(`点击次数:${this.tapCount}`).fontSize(20).fontWeight(FontWeight.Bold).fontColor('#4D96FF').margin({bottom:8})if(this.lastTapTime){Text(`上次点击:${this.lastTapTime}`).fontSize(12).fontColor('#999999')}用条件渲染显示上次点击时间——第一次点击前不显示。
完整代码
@Entry@Componentstruct TapGestureBasic{@StatetapCount:number=0@StatelastTapTime:string=''build(){Column(){Column(){Text('点击手势').fontSize(16).fontWeight(FontWeight.Bold).margin({bottom:16})Text(`点击次数:${this.tapCount}`).fontSize(20).fontWeight(FontWeight.Bold).fontColor('#4D96FF').margin({bottom:8})if(this.lastTapTime){Text(`上次点击:${this.lastTapTime}`).fontSize(12).fontColor('#999999')}Column(){Text('点击区域').fontSize(16).fontColor('#FFFFFF')}.width('100%').height(120).backgroundColor('#4D96FF').borderRadius(16).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).margin({top:20}).onClick(()=>{this.tapCount++this.lastTapTime=newDate().toLocaleTimeString()})Column(){Text('手势说明:').fontSize(13).fontColor('#999999').margin({bottom:8})Text('• onClick 是最基础的点击事件').fontSize(12).fontColor('#AAAAAA').margin({bottom:4})Text('• 可用于按钮、容器等各种组件').fontSize(12).fontColor('#AAAAAA')}.width('100%').margin({top:24}).padding(12).backgroundColor('#F8F8F8').borderRadius(8)}.width('100%').padding(24).backgroundColor('#FFFFFF').borderRadius(12)}.width('100%').height('100%').backgroundColor('#F5F6FA').padding(16)}}常见问题
Q:任何组件都能加 onClick 吗?
是的。Column、Row、Stack、Text、Image、Button……几乎所有可见组件都支持onClick。不过需要注意,如果组件没有设置宽高或背景色,可能无法响应点击(因为没有可点击的区域)。
Q:onClick 和 onTouch 有什么区别?
onTouch能获取更底层的触摸事件,包括按下(Down)、抬起(Up)、移动(Move)、取消(Cancel)。onClick只在"按下 + 抬起"完成时触发。大多数情况下onClick就够了。
Q:双击怎么实现?
用TapGesture并设置count参数:
.gesture(TapGesture({count:2}).onAction(()=>{// 双击逻辑}))进阶技巧
点击反馈效果
加上.scale和动画实现点击缩放效果:
@StateisPressed:boolean=falseColumn(){/* ... */}.scale({x:this.isPressed?0.95:1,y:this.isPressed?0.95:1}).animation({duration:100}).onTouch((event:TouchEvent)=>{if(event.type===TouchType.Down)this.isPressed=trueif(event.type===TouchType.Up||event.type===TouchType.Cancel){this.isPressed=false}}).onClick(()=>{// 点击逻辑})防重复点击
防止用户快速连续点击触发多次操作:
@StatelastClickTime:number=0.onClick(()=>{constnow=Date.now()if(now-this.lastClickTime<500)return// 500ms 内不响应this.lastClickTime=now// 正常点击逻辑})写在最后
onClick是最简单的手势,也是用得最多的手势。给它一个回调函数,就能响应用户的点击操作。记住两个要点:组件要有可点击区域(设宽高或背景),以及注意防重复点击。
后续文章会讲更复杂的手势——长按、拖拽、缩放、旋转。但不管什么手势,核心模式都一样:.gesture(XXX().onAction(callback))。掌握了onClick,后面的手势学起来就很快了。