1# 自定义手势判定 2 3为组件提供自定义手势判定能力。开发者可根据需要,在手势识别期间,决定是否响应手势。 4 5> **说明:** 6> 7> 从API Version 11开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 8 9 10## onGestureJudgeBegin 11onGestureJudgeBegin(callback: (gestureInfo: GestureInfo, event: BaseGestureEvent) => GestureJudgeResult): T 12 13**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 14 15**参数:** 16| 参数名 | 参数类型 | 必填 | 参数描述 | 17| ---------- | -------------------------- | ------- | ----------------------------- | 18| callback | (gestureInfo: [GestureInfo](#gestureinfo对象说明), event: [BaseGestureEvent](#basegestureevent对象说明)) => [GestureJudgeResult](#gesturejudgeresult11) | 是 | 给组件绑定自定义手势判定回调,当绑定到该组件的手势被接受时,会触发用户定义的回调来获取结果。 | 19 20**返回值:** 21 22| 类型 | 说明 | 23| -------- | -------- | 24| T | 返回当前组件。 | 25 26 27## GestureJudgeResult<sup>11+</sup> 28 29**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 30 31**系统能力:** SystemCapability.ArkUI.ArkUI.Full 32 33| 名称 | 描述 | 34| ----- | -------------------------------------- | 35| CONTINUE | 不影响系统手势判定流程。| 36| REJECT | 对于用户自定义的手势判定结果为失败。| 37 38## GestureInfo对象说明 39 40**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 41 42| 名称 | 类型 | 描述 | 43| --------------- | ------------------------- | -----------| 44| tag | string | 手势标记。<br/>**说明:**<br/>如果未设置事件标识tag属性的情况下,此处tag不返回或者返回undefined。 | 45| type | [GestureControl.GestureType](#gesturetype12) | 手势类型。<br/>**说明:**<br/> 当手势为未暴露类型的系统内置手势事件时,type的值为-1。 | 46| isSystemGesture | boolean | 判断当前手势是否是组件自带的手势。true表示是组件自带的手势,false表示非组件自带手势。<br/>默认值:false | 47 48## GestureType<sup>12+</sup> 49 50**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 51 52**系统能力:** SystemCapability.ArkUI.ArkUI.Full 53 54| 名称 | 值 | 描述 | 55| ----- | -------- | -------------------------------------- | 56| TAP_GESTURE | 0 | 点击手势| 57| LONG_PRESS_GESTURE | 1 | 长按手势| 58| PAN_GESTURE | 2 | 拖动手势| 59| PINCH_GESTURE | 3 | 捏合手势| 60| SWIPE_GESTURE | 4 | 滑动手势| 61| ROTATION_GESTURE | 5 | 旋转手势| 62| DRAG | 6 | 拖拽| 63| CLICK | 7 | 点击| 64 65## BaseEvent对象说明<sup>8+</sup> 66 67 68| 名称 | 类型 | 描述 | 69| ---------| ---------------------------------------- | -----------| 70| target | [EventTarget](ts-universal-events-click.md#eventtarget8对象说明) | 触发手势事件的元素对象显示区域。<br/>**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 71| timestamp| number | 事件时间戳,触发事件时距离系统启动的时间间隔。<br>单位:ns<br/>**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 72| source | [SourceType](ts-gesture-settings.md#sourcetype枚举说明) | 事件输入设备。<br/>**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 73| pressure<sup>9+</sup> | number | 按压的压力大小。<br/>默认值:0<br/>取值范围:[0,1],典型值0.913168,压感大小与数值正相关。<br/>**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 74| tiltX<sup>9+</sup> | number | 手写笔在设备平面上的投影与设备平面X轴的夹角。<br/>**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 75| tiltY<sup>9+</sup> | number | 手写笔在设备平面上的投影与设备平面Y轴的夹角。<br/>**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 76| rollAngle<sup>17+</sup> | number | 手写笔与设备平面的夹角。<br/>**卡片能力:** 从API version 17开始,该接口支持在ArkTS卡片中使用。<br/>**原子化服务API:** 从API version 17开始,该接口支持在原子化服务中使用。 | 77| sourceTool<sup>9+</sup> | [SourceTool](ts-gesture-settings.md#sourcetool枚举说明9) | 事件输入源。<br/>**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 78| axisHorizontal<sup>12+</sup> | number | 水平轴值。<br/>**说明:**<br/>当前仅在由鼠标滚轮或者触控板双指滑动场景下触发的Pan手势中可以获取。<br/>**卡片能力:** 从API version 12开始,该接口支持在ArkTS卡片中使用。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 79| axisVertical<sup>12+</sup> | number | 垂直轴值。<br/>**说明:**<br/>当前仅在由鼠标滚轮或者触控板双指滑动场景下触发的Pan手势中可以获取。<br/>**卡片能力:** 从API version 12开始,该接口支持在ArkTS卡片中使用。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 80| getModifierKeyState<sup>12+</sup> | (Array<string>) => bool | 获取功能键按压状态。报错信息请参考以下错误码。支持功能键 'Ctrl'\|'Alt'\|'Shift'\|'Fn',设备外接带Fn键的键盘不支持Fn键查询。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 81| deviceId<sup>12+</sup> | number | 触发当前事件的输入设备ID。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 82| targetDisplayId<sup>15+</sup> | number | 事件发生的屏幕ID。 <br/>默认值:0<br />取值范围:[0, +∞)<br />**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。 | 83 84**错误码**: 85 86以下错误码详细介绍请参考[通用错误码](../../errorcode-universal.md)。 87 88| 错误码ID | 错误信息 | 89| ------- | -------- | 90| 401 | Parameter error. Possible causes: 1. Incorrect parameter types. 2. Parameter verification failed. | 91 92## BaseGestureEvent对象说明 93继承于[BaseEvent](#baseevent对象说明8)。 94 95**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 96 97| 名称 | 类型 | 描述 | 98| --------- | ---------------------------------------- | -----------| 99| fingerList | [FingerInfo[]](ts-gesture-settings.md#fingerinfo对象说明8) | 触发事件的所有手指信息。 | 100 101## TapGestureEvent对象说明 102继承于[BaseGestureEvent](#basegestureevent对象说明)。可将该对象作为[onGestureJudgeBegin](#ongesturejudgebegin)的event参数来传递。 103 104**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 105 106## LongPressGestureEvent对象说明 107继承于[BaseGestureEvent](#basegestureevent对象说明)。可将该对象作为[onGestureJudgeBegin](#ongesturejudgebegin)的event参数来传递。 108 109**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 110 111| 名称 | 类型 | 描述 | 112| --------- | ---------------------------------------- | -----------| 113| repeat | boolean | 是否为重复触发事件。true表示为重复触发事件,false表示非重复触发事件。 | 114 115## PanGestureEvent对象说明 116继承于[BaseGestureEvent](#basegestureevent对象说明)。可将该对象作为[onGestureJudgeBegin](#ongesturejudgebegin)的event参数来传递。 117 118**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 119 120| 名称 | 类型 | 描述 | 121| --------- | ---------------------------------------- | -----------| 122| offsetX | number | 手势事件x轴相对当前组件元素原始区域的偏移量,单位为vp,从左向右滑动offsetX为正,反之为负。 | 123| offsetY | number | 手势事件y轴相对当前组件元素原始区域的偏移量,单位为vp,从上向下滑动offsetY为正,反之为负。 | 124| velocityX | number | 获取当前手势的x轴方向速度。坐标轴原点为屏幕左上角,分正负方向速度,从左往右为正,反之为负。单位为vp/s。 | 125| velocityY | number | 获取当前手势的y轴方向速度。坐标轴原点为屏幕左上角,分正负方向速度,从上往下为正,反之为负。单位为vp/s。| 126| velocity | number | 获取当前的主方向速度。为xy轴方向速度的平方和的算术平方根。单位为vp/s。 | 127 128## PinchGestureEvent对象说明 129 130**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 131 132继承于[BaseGestureEvent](#basegestureevent对象说明)。可将该对象作为[onGestureJudgeBegin](#ongesturejudgebegin)的event参数来传递。 133| 名称 | 类型 | 描述 | 134| ------------ | ---------------------------------------- | -----------| 135| scale | number | 缩放比例。 | 136| pinchCenterX | number | 捏合手势中心点相对于当前组件元素原始区域左上角x轴坐标,单位为vp。 | 137| pinchCenterY | number | 捏合手势中心点相对于当前组件元素原始区域左上角y轴坐标,单位为vp。 | 138 139## RotationGestureEvent对象说明 140 141**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 142 143继承于[BaseGestureEvent](#basegestureevent对象说明)。可将该对象作为[onGestureJudgeBegin](#ongesturejudgebegin)的event参数来传递。 144| 名称 | 类型 | 描述 | 145| ------------ | ---------------------------------------- | -----------| 146| angle | number | 表示旋转角度,单位为deg。<br/>**说明:**<br/>角度计算方式:滑动手势被识别到后,连接两根手指之间的线被识别为起始线条,随着手指的滑动,手指之间的线条会发生旋转,根据起始线条两端点和当前线条两端点的坐标,使用反正切函数分别计算其相对于水平方向的夹角,最后arctan2(cy2-cy1,cx2-cx1)-arctan2(y2-y1,x2-x1)为旋转的角度。以起始线条为坐标系,顺时针旋转为0到180度,逆时针旋转为-180到0度。 | 147 148## SwipeGestureEvent对象说明 149继承于[BaseGestureEvent](#basegestureevent对象说明)。可将该对象作为[onGestureJudgeBegin](#ongesturejudgebegin)的event参数来传递。 150 151**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 152 153| 名称 | 类型 | 描述 | 154| ------------ | ---------------------------------------- | -----------| 155| angle | number | 表示滑动手势的角度,即两根手指间的线段与水平方向的夹角变化的度数,单位为deg。<br/>**说明:**<br/>角度计算方式:滑动手势被识别到后,连接两根手指之间的线被识别为起始线条,随着手指的滑动,手指之间的线条会发生旋转,根据起始线条两端点和当前线条两端点的坐标,使用反正切函数分别计算其相对于水平方向的夹角,最后arctan2(cy2-cy1,cx2-cx1)-arctan2(y2-y1,x2-x1)为旋转的角度。以起始线条为坐标系,顺时针旋转为0到180度,逆时针旋转为-180到0度。| 156| speed | number | 滑动手势速度,即所有手指相对当前组件元素原始区域滑动的平均速度,单位为vp/s。 | 157## 示例 158 159### 示例1(自定义手势判定) 160 161该示例通过配置onGestureJudgeBegin实现了对长按、滑动和拖动手势的自定义判定。 162 163```ts 164// xxx.ets 165@Entry 166@Component 167struct Index { 168 @State message: string = ''; 169 170 build() { 171 Column() { 172 Row({ space: 20 }) { 173 Text(this.message).width(200).height(80).backgroundColor(Color.Pink) 174 .fontSize(25) 175 }.margin(20) 176 } 177 .width('100%') 178 .height(200) 179 .borderWidth(2) 180 .onDragStart(() => { 181 this.message = 'drag' 182 console.log("Drag start.") 183 }) 184 .gesture( 185 TapGesture() 186 .tag("tap1")// 设置点击手势标志 187 .onAction(() => { 188 this.message = 'tap1' 189 }) 190 ) 191 .gesture( 192 LongPressGesture() 193 .tag("longPress1")// 设置长按手势标志 194 .onAction(() => { 195 this.message = 'longPress' 196 }) 197 ) 198 .gesture( 199 SwipeGesture() 200 .tag("swipe1")// 设置滑动手势标志 201 .onAction(() => { 202 this.message = 'swipe1' 203 }) 204 ) 205 .gesture( 206 PanGesture() 207 .tag("pan1")// 设置拖动手势标志 208 .onActionStart(() => { 209 this.message = 'pan1' 210 }) 211 ) 212 .onGestureJudgeBegin((gestureInfo: GestureInfo, event: BaseGestureEvent) => { 213 // 若该手势类型为长按手势,转换为长按手势事件 214 if (gestureInfo.type == GestureControl.GestureType.LONG_PRESS_GESTURE) { 215 let longPressEvent = event as LongPressGestureEvent; 216 console.log("repeat " + longPressEvent.repeat) 217 } 218 // 若该手势类型为滑动手势,转换为滑动手势事件 219 if (gestureInfo.type == GestureControl.GestureType.SWIPE_GESTURE) { 220 let swipeEvent = event as SwipeGestureEvent; 221 console.log("angle " + swipeEvent.angle) 222 } 223 // 若该手势类型为拖动手势,转换为拖动手势事件 224 if (gestureInfo.type == GestureControl.GestureType.PAN_GESTURE) { 225 let panEvent = event as PanGestureEvent; 226 console.log("velocity " + panEvent.velocity) 227 } 228 // 自定义判定标准 229 if (gestureInfo.type == GestureControl.GestureType.DRAG) { 230 // 返回 REJECT 会使拖动手势失败 231 return GestureJudgeResult.REJECT; 232 } else if (gestureInfo.tag == 'longPress1' && event.fingerList.length > 0 && event.fingerList[0].localY < 100) { 233 // 返回 CONTINUE 将保持系统判定。 234 return GestureJudgeResult.CONTINUE; 235 } 236 return GestureJudgeResult.CONTINUE; 237 }) 238 } 239} 240``` 241 242 243### 示例2(自定义区域手势判定) 244 245该示例通过配置onGestureJudgeBegin判定区域决定长按手势和拖拽是否响应。 246 247```ts 248// xxx.ets 249import { PromptAction } from '@kit.ArkUI'; 250 251@Entry 252@Component 253struct Index { 254 scroller: Scroller = new Scroller() 255 promptAction: PromptAction = this.getUIContext().getPromptAction(); 256 257 build() { 258 Scroll(this.scroller) { 259 Column({ space: 8 }) { 260 Text("Drag 上下两层 上层绑定长按,下层绑定拖拽。先长按后平移上半区红色区域只会响应长按,先长按后平移下半区蓝色区域只会响应拖拽").width('100%').fontSize(20).fontColor('0xffdd00') 261 .backgroundColor(0xeeddaa00) 262 Stack({ alignContent: Alignment.Center }) { 263 Column() { 264 // 模拟上半区和下半区 265 Stack().width('200vp').height('100vp').backgroundColor(Color.Red) 266 Stack().width('200vp').height('100vp').backgroundColor(Color.Blue) 267 }.width('200vp').height('200vp') 268 // Stack的下半区是绑定了拖动手势的图像区域。 269 Image($r('sys.media.ohos_app_icon')) 270 .draggable(true) 271 .onDragStart(()=>{ 272 this.promptAction.showToast({ message: "Drag 下半区蓝色区域,Image响应" }) 273 }) 274 .width('200vp').height('200vp') 275 // Stack的上半区是绑定了长按手势的浮动区域。 276 Stack() { 277 } 278 .width('200vp') 279 .height('200vp') 280 .hitTestBehavior(HitTestMode.Transparent) 281 .onGestureJudgeBegin((gestureInfo: GestureInfo, event: BaseGestureEvent) => { 282 // 确定tag标志是否有值 283 if (gestureInfo.tag) { 284 console.log("gestureInfo tag" + gestureInfo.tag.toString()) 285 } 286 console.log("gestureInfo Type " + gestureInfo.type.toString() + " isSystemGesture " + gestureInfo.isSystemGesture); 287 console.log("pressure " + event.pressure + " fingerList.length " + event.fingerList.length 288 + " timeStamp " + event.timestamp + " sourceType " + event.source.toString() + " titleX " + event.tiltX + " titleY " + event.tiltY + " rollAngle " + event.rollAngle + " sourcePool " + event.sourceTool.toString()); 289 // 如果是长按类型手势,判断点击的位置是否在上半区 290 if (gestureInfo.type == GestureControl.GestureType.LONG_PRESS_GESTURE) { 291 if (event.fingerList.length > 0 && event.fingerList[0].localY < 100) { 292 return GestureJudgeResult.CONTINUE 293 } else { 294 return GestureJudgeResult.REJECT 295 } 296 } 297 return GestureJudgeResult.CONTINUE 298 }) 299 .gesture(GestureGroup(GestureMode.Parallel, 300 LongPressGesture() 301 .onAction((event: GestureEvent) => { 302 this.promptAction.showToast({ message: "LongPressGesture 长按上半区 红色区域,红色区域响应" }) 303 }) 304 .tag("tap111") 305 )) 306 307 }.width('100%') 308 }.width('100%') 309 } 310 } 311} 312``` 313