1# 自定义手势判定 2 3为组件提供自定义手势判定能力。开发者可根据需要,在手势识别期间,决定是否响应手势。 4 5> **说明:** 6> 7> 从API Version 11开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 8 9 10## onGestureJudgeBegin 11onGestureJudgeBegin(callback: (gestureInfo: GestureInfo, event: BaseGestureEvent) => GestureJudgeResult): T 12 13**参数:** 14| 参数名 | 参数类型 | 必填 | 参数描述 | 15| ---------- | -------------------------- | ------- | ----------------------------- | 16| callback | (gestureInfo: [GestureInfo](#gestureinfo对象说明), event: [BaseGestureEvent](#basegestureevent对象说明)) => [GestureJudgeResult](ts-appendix-enums.md#gesturejudgeresult11) | 是 | 给组件绑定自定义手势判定回调,当绑定到该组件的手势被接受时,会触发用户定义的回调来获取结果。 | 17 18**返回值:** 19 20| 类型 | 说明 | 21| -------- | -------- | 22| T | 返回当前组件。 | 23 24## GestureInfo对象说明 25 26| 名称 | 类型 | 描述 | 27| --------------- | ------------------------- | -----------| 28| tag | string | 手势标记。<br/>**说明:**<br/>如果未设置事件标识tag属性的情况下,此处tag不返回或者返回undefined。 | 29| type | [GestureControl.GestureType](ts-appendix-enums.md#gesturetype11) | 手势类型。 | 30| isSystemGesture | boolean | 判断当前手势是否为系统手势。| 31 32## BaseEvent对象说明 33| 名称 | 类型 | 描述 | 34| ---------| ---------------------------------------- | -----------| 35| target | [EventTarget](ts-universal-events-click.md#eventtarget8对象说明) | 触发手势事件的元素对象显示区域。 | 36| timestamp| number | 事件时间戳。 | 37| source | [SourceType](ts-gesture-settings.md#sourcetype枚举说明) | 事件输入设备。 | 38| pressure | number | 按压的压力大小。 | 39| titleX | number | 手写笔在设备平面上的投影与设备平面X轴的夹角。 | 40| titleY | number | 手写笔在设备平面上的投影与设备平面Y轴的夹角。 | 41| sourceTool | [SourceTool](ts-gesture-settings.md#sourcetool枚举说明9) | 事件输入源。 | 42## BaseGestureEvent对象说明 43继承于[BaseEvent](#baseevent对象说明)。 44| 名称 | 类型 | 描述 | 45| --------- | ---------------------------------------- | -----------| 46| fingerList | [FingerInfo[]](ts-gesture-settings.md#fingerinfo对象说明8) | 触发事件的所有手指信息。 | 47 48## TapGestureEvent对象说明 49继承于[BaseGestureEvent](#basegestureevent对象说明)。可将该对象作为[onGestureJudgeBegin](#ongesturejudgebegin)的event参数来传递。 50 51## LongPressGestureEvent对象说明 52继承于[BaseGestureEvent](#basegestureevent对象说明)。可将该对象作为[onGestureJudgeBegin](#ongesturejudgebegin)的event参数来传递。 53| 名称 | 类型 | 描述 | 54| --------- | ---------------------------------------- | -----------| 55| repeat | boolean | 是否为重复触发事件。 | 56 57## PanGestureEvent对象说明 58继承于[BaseGestureEvent](#basegestureevent对象说明)。可将该对象作为[onGestureJudgeBegin](#ongesturejudgebegin)的event参数来传递。 59| 名称 | 类型 | 描述 | 60| --------- | ---------------------------------------- | -----------| 61| offsetX | number | 手势事件x轴相对当前组件元素原始区域的偏移量,单位为vp,从左向右滑动offsetX为正,反之为负。 | 62| offsetY | number | 手势事件y轴相对当前组件元素原始区域的偏移量,单位为vp,从上向下滑动offsetY为正,反之为负。 | 63| velocityX | number | 获取当前手势的x轴方向速度。坐标轴原点为屏幕左上角,分正负方向速度,从左往右为正,反之为负。 | 64| velocityY | number | 获取当前手势的y轴方向速度。坐标轴原点为屏幕左上角,分正负方向速度,从上往下为正,反之为负。| 65| velocity | number | 获取当前的主方向速度。为xy轴方向速度的平方和的算术平方根。 | 66 67## PinchGestureEvent对象说明 68继承于[BaseGestureEvent](#basegestureevent对象说明)。可将该对象作为[onGestureJudgeBegin](#ongesturejudgebegin)的event参数来传递。 69| 名称 | 类型 | 描述 | 70| ------------ | ---------------------------------------- | -----------| 71| scale | number | 缩放比例。 | 72| pinchCenterX | number | 捏合手势中心点相对于当前组件元素原始区域左上角x轴坐标,单位为vp。 | 73| pinchCenterY | number | 捏合手势中心点相对于当前组件元素原始区域左上角y轴坐标,单位为vp。 | 74 75## RotationGestureEvent对象说明 76继承于[BaseGestureEvent](#basegestureevent对象说明)。可将该对象作为[onGestureJudgeBegin](#ongesturejudgebegin)的event参数来传递。 77| 名称 | 类型 | 描述 | 78| ------------ | ---------------------------------------- | -----------| 79| angle | number | 表示旋转角度,单位为deg。<br/>**说明:**<br/>角度计算方式:滑动手势被识别到后,连接两根手指之间的线被识别为起始线条,随着手指的滑动,手指之间的线条会发生旋转,根据起始线条两端点和当前线条两端点的坐标,使用反正切函数分别计算其相对于水平方向的夹角,最后arctan2(cy2-cy1,cx2-cx1)-arctan2(y2-y1,x2-x1)为旋转的角度。以起始线条为坐标系,顺时针旋转为0到180度,逆时针旋转为-180到0度。 | 80 81## SwipeGestureEvent对象说明 82继承于[BaseGestureEvent](#basegestureevent对象说明)。可将该对象作为[onGestureJudgeBegin](#ongesturejudgebegin)的event参数来传递。 83| 名称 | 类型 | 描述 | 84| ------------ | ---------------------------------------- | -----------| 85| angle | number | 表示滑动手势的角度,即两根手指间的线段与水平方向的夹角变化的度数,单位为deg。<br/>**说明:**<br/>角度计算方式:滑动手势被识别到后,连接两根手指之间的线被识别为起始线条,随着手指的滑动,手指之间的线条会发生旋转,根据起始线条两端点和当前线条两端点的坐标,使用反正切函数分别计算其相对于水平方向的夹角,最后arctan2(cy2-cy1,cx2-cx1)-arctan2(y2-y1,x2-x1)为旋转的角度。以起始线条为坐标系,顺时针旋转为0到180度,逆时针旋转为-180到0度。| 86| speed | number | 滑动手势速度,即所有手指相对当前组件元素原始区域滑动的平均速度,单位为vp/秒。 | 87## 示例 88 89### 示例1 90```ts 91// xxx.ets 92@Entry 93@Component 94struct Index { 95 @State message: string = ''; 96 97 build() { 98 Column() { 99 Row({ space: 20 }) { 100 Text(this.message).width(100).height(40).backgroundColor(Color.Pink) 101 }.margin(20) 102 } 103 .width('100%') 104 .height(200) 105 .borderWidth(2) 106 .onDragStart(() => { 107 this.message = 'drag' 108 console.log("Drag start.") 109 }) 110 .gesture( 111 TapGesture() 112 .tag("tap1")// 设置点击手势标志 113 ) 114 .gesture( 115 LongPressGesture() 116 .tag("longPress1")// 设置长按手势标志 117 .onAction(() => { 118 this.message = 'longPress' 119 }) 120 ) 121 .gesture( 122 SwipeGesture() 123 .tag("swipe1")// 设置滑动手势标志 124 ) 125 .gesture( 126 PanGesture() 127 .tag("pan1")// 设置拖动手势标志 128 ) 129 .onGestureJudgeBegin((gestureInfo: GestureInfo, event: BaseGestureEvent) => { 130 // 若该手势类型为长按手势,转换为长按手势事件 131 if (gestureInfo.type == GestureControl.GestureType.LONG_PRESS_GESTURE) { 132 let longPressEvent = event as LongPressGestureEvent; 133 console.log("repeat " + longPressEvent.repeat) 134 } 135 // 若该手势类型为滑动手势,转换为滑动手势事件 136 if (gestureInfo.type == GestureControl.GestureType.SWIPE_GESTURE) { 137 let swipeEvent = event as SwipeGestureEvent; 138 console.log("angle " + swipeEvent.angle) 139 } 140 // 若该手势类型为拖动手势,转换为拖动手势事件 141 if (gestureInfo.type == GestureControl.GestureType.PAN_GESTURE) { 142 let panEvent = event as PanGestureEvent; 143 console.log("velocity " + panEvent.velocity) 144 } 145 // 自定义判定标准 146 if (gestureInfo.type == GestureControl.GestureType.DRAG) { 147 // 返回 REJECT 会使拖动手势失败 148 return GestureJudgeResult.REJECT; 149 } else if (gestureInfo.tag == 'longPress1' && event.fingerList.length > 0 && event.fingerList[0].localY < 100) { 150 // 返回 CONTINUE 将保持系统判定。 151 return GestureJudgeResult.CONTINUE; 152 } 153 return GestureJudgeResult.CONTINUE; 154 }) 155 } 156} 157``` 158### 示例2 159```ts 160// xxx.ets 161import promptAction from '@ohos.promptAction'; 162 163@Entry 164@Component 165struct Index { 166 scroller: Scroller = new Scroller() 167 168 build() { 169 Scroll(this.scroller) { 170 Column({ space: 8 }) { 171 Text("Drag 上下两层 上层绑定长按,下层绑定拖拽。先长按后平移上半区红色区域只会响应长按,先长按后平移下半区蓝色区域只会响应拖拽").width('100%').fontSize(20).fontColor('0xffdd00') 172 .backgroundColor(0xeeddaa00) 173 Stack({ alignContent: Alignment.Center }) { 174 Column() { 175 // 模拟上半区和下半区 176 Stack().width('200vp').height('100vp').backgroundColor(Color.Red) 177 Stack().width('200vp').height('100vp').backgroundColor(Color.Blue) 178 }.width('200vp').height('200vp') 179 // Stack的下半区是绑定了拖动手势的图像区域。 180 Image($r('sys.media.ohos_app_icon')) 181 .onDragStart(()=>{ 182 promptAction.showToast({ message: "Drag 下半区蓝色区域,Image响应" }) 183 }) 184 .width('200vp').height('200vp') 185 // Stack的上半区是绑定了长按手势的浮动区域。 186 Stack() { 187 } 188 .width('200vp') 189 .height('200vp') 190 .hitTestBehavior(HitTestMode.Transparent) 191 .onGestureJudgeBegin((gestureInfo: GestureInfo, event: BaseGestureEvent) => { 192 // 确定tag标志是否有值 193 if (gestureInfo.tag) { 194 console.log("gestureInfo tag" + gestureInfo.tag.toString()) 195 } 196 console.log("gestureInfo Type " + gestureInfo.type.toString() + " isSystemGesture " + gestureInfo.isSystemGesture); 197 console.log("pressure " + event.pressure + " fingerList.length " + event.fingerList.length 198 + " timeStamp " + event.timestamp + " sourceType " + event.source.toString() + " titleX " + event.tiltX + " titleY " + event.tiltY + " sourcePool " + event.sourceTool.toString()); 199 // 如果是长按类型手势,判断点击的位置是否在上半区 200 if (gestureInfo.type == GestureControl.GestureType.LONG_PRESS_GESTURE) { 201 if (event.fingerList.length > 0 && event.fingerList[0].localY < 100) { 202 return GestureJudgeResult.CONTINUE 203 } else { 204 return GestureJudgeResult.REJECT 205 } 206 } 207 return GestureJudgeResult.CONTINUE 208 }) 209 .gesture(GestureGroup(GestureMode.Parallel, 210 LongPressGesture() 211 .onAction((event: GestureEvent) => { 212 promptAction.showToast({ message: "LongPressGesture 长按上半区 红色区域,红色区域响应" }) 213 }) 214 .tag("tap111") 215 )) 216 217 }.width('100%') 218 }.width('100%') 219 } 220 } 221} 222```