From a76e9540723dc50be1c0445a2a6600ba588f735d Mon Sep 17 00:00:00 2001 From: lukecurran Date: Thu, 23 May 2019 09:08:00 -0500 Subject: [PATCH 1/9] Fix simultaneous tap gestures for iOS --- apps/app/ui-tests-app/events/gestures.ts | 59 +++++++++++++------- apps/package.json | 6 +- tns-core-modules/ui/gestures/gestures.ios.ts | 48 ++++++++++------ 3 files changed, 74 insertions(+), 39 deletions(-) diff --git a/apps/app/ui-tests-app/events/gestures.ts b/apps/app/ui-tests-app/events/gestures.ts index 264106db22..f378b443aa 100644 --- a/apps/app/ui-tests-app/events/gestures.ts +++ b/apps/app/ui-tests-app/events/gestures.ts @@ -7,43 +7,49 @@ import * as stackLayoutModule from "tns-core-modules/ui/layouts/stack-layout"; export function createPage() { - var stack = new stackLayoutModule.StackLayout(); - var labelHeight = Math.round(deviceProperties.screen.mainScreen.heightPixels / (7 * deviceProperties.screen.mainScreen.scale)); - var stopButton = new button.Button(); + const stack = new stackLayoutModule.StackLayout(); + const labelHeight = Math.round(deviceProperties.screen.mainScreen.heightPixels / (7 * deviceProperties.screen.mainScreen.scale)); + const stopButton = new button.Button(); stopButton.text = "Stop Detecting Gestures"; stack.addChild(stopButton); - var tapLabel = new labelModule.Label(); + const tapLabel = new labelModule.Label(); tapLabel.text = "Tap here"; stack.addChild(tapLabel); - var doubletapLabel = new labelModule.Label(); + const doubletapLabel = new labelModule.Label(); doubletapLabel.text = "Double Tap here"; stack.addChild(doubletapLabel); - var longpressLabel = new labelModule.Label(); + const longpressLabel = new labelModule.Label(); longpressLabel.text = "Long Press here"; stack.addChild(longpressLabel); - var swipeLabel = new labelModule.Label(); + const tapAndDoubleTapLabel = new labelModule.Label(); + tapAndDoubleTapLabel.height = labelHeight; + tapAndDoubleTapLabel.text = "Tap or Double Tap"; + tapAndDoubleTapLabel.textWrap = true; + stack.addChild(tapAndDoubleTapLabel); + + const swipeLabel = new labelModule.Label(); swipeLabel.height = labelHeight; swipeLabel.text = "Swipe here"; swipeLabel.textWrap = true; stack.addChild(swipeLabel); - var panLabel = new labelModule.Label(); + const panLabel = new labelModule.Label(); panLabel.height = labelHeight; panLabel.text = "Pan here"; panLabel.textWrap = true; stack.addChild(panLabel); - var pinchLabel = new labelModule.Label(); + const pinchLabel = new labelModule.Label(); pinchLabel.height = labelHeight; pinchLabel.text = "Pinch here"; pinchLabel.textWrap = true; stack.addChild(pinchLabel); - var rotaionLabel = new labelModule.Label(); + const rotaionLabel = new labelModule.Label(); rotaionLabel.height = labelHeight; rotaionLabel.text = "Rotate here"; rotaionLabel.textWrap = true; @@ -57,6 +63,8 @@ export function createPage() { observer5.disconnect(); observer6.disconnect(); observer7.disconnect(); + observer8.disconnect(); + observer9.disconnect(); tapLabel.text = "Gestures detection disabled"; doubletapLabel.text = "Gestures detection disabled"; longpressLabel.text = "Gestures detection disabled"; @@ -64,56 +72,69 @@ export function createPage() { panLabel.text = "Gestures detection disabled"; pinchLabel.text = "Gestures detection disabled"; rotaionLabel.text = "Gestures detection disabled"; + tapAndDoubleTapLabel.text = "Gestures detection disabled"; }); tapLabel.on(gestures.GestureTypes.tap, function (args: gestures.GestureEventData) { tapLabel.text = "Tap gesture detected, " + (args.object === tapLabel); }); - var observer1 = tapLabel.getGestureObservers(gestures.GestureTypes.tap)[0]; + const observer1 = tapLabel.getGestureObservers(gestures.GestureTypes.tap)[0]; doubletapLabel.on(gestures.GestureTypes.doubleTap, function (args: gestures.GestureEventData) { doubletapLabel.text = "Double Tap gesture detected, " + (args.object === doubletapLabel); }); - var observer2 = doubletapLabel.getGestureObservers(gestures.GestureTypes.doubleTap)[0]; + const observer2 = doubletapLabel.getGestureObservers(gestures.GestureTypes.doubleTap)[0]; longpressLabel.on(gestures.GestureTypes.longPress, function (args: gestures.GestureEventData) { longpressLabel.text = "Long Press gesture detected, " + (args.object === longpressLabel); }); - var observer3 = longpressLabel.getGestureObservers(gestures.GestureTypes.longPress)[0]; + const observer3 = longpressLabel.getGestureObservers(gestures.GestureTypes.longPress)[0]; swipeLabel.on(gestures.GestureTypes.swipe, function (args: gestures.SwipeGestureEventData) { swipeLabel.text = "Swipe Direction: " + args.direction + ", " + (args.object === swipeLabel); // + getStateAsString(args.state); }); - var observer4 = swipeLabel.getGestureObservers(gestures.GestureTypes.swipe)[0]; + const observer4 = swipeLabel.getGestureObservers(gestures.GestureTypes.swipe)[0]; panLabel.on(gestures.GestureTypes.pan, function (args: gestures.PanGestureEventData) { panLabel.text = "Pan deltaX:" + Math.round(args.deltaX) + "; deltaY:" + Math.round(args.deltaY) + ";" + ", " + (args.object === panLabel) + getStateAsString(args.state); }); - var observer5 = panLabel.getGestureObservers(gestures.GestureTypes.pan)[0]; + const observer5 = panLabel.getGestureObservers(gestures.GestureTypes.pan)[0]; pinchLabel.on(gestures.GestureTypes.pinch, function (args: gestures.PinchGestureEventData) { pinchLabel.text = "Pinch Scale: " + Math.round(args.scale) + ", " + (args.object === pinchLabel) + getStateAsString(args.state); }); - var observer6 = pinchLabel.getGestureObservers(gestures.GestureTypes.pinch)[0]; + const observer6 = pinchLabel.getGestureObservers(gestures.GestureTypes.pinch)[0]; rotaionLabel.on(gestures.GestureTypes.rotation, function (args: gestures.RotationGestureEventData) { rotaionLabel.text = "Rotation: " + Math.round(args.rotation) + ", " + (args.object === rotaionLabel) + getStateAsString(args.state); }); - var observer7 = rotaionLabel.getGestureObservers(gestures.GestureTypes.rotation)[0]; + const observer7 = rotaionLabel.getGestureObservers(gestures.GestureTypes.rotation)[0]; + + tapAndDoubleTapLabel.on(gestures.GestureTypes.doubleTap, function (args: gestures.GestureEventData) { + tapAndDoubleTapLabel.text = "Last action: Double tap gesture, " + (args.object === tapAndDoubleTapLabel); + }); + + const observer8 = tapAndDoubleTapLabel.getGestureObservers(gestures.GestureTypes.doubleTap)[0]; + + tapAndDoubleTapLabel.on(gestures.GestureTypes.tap, function (args: gestures.GestureEventData) { + tapAndDoubleTapLabel.text = "Last action: Tap gesture, " + (args.object === tapAndDoubleTapLabel); + }); + + const observer9 = tapAndDoubleTapLabel.getGestureObservers(gestures.GestureTypes.tap)[0]; - var page = new pages.Page(); + const page = new pages.Page(); page.content = stack; return page; } -var states = new Array(); +const states = new Array(); function getStateAsString(state: gestures.GestureStateTypes): string { if (state === gestures.GestureStateTypes.began) { states.length = 0; diff --git a/apps/package.json b/apps/package.json index a548304ff2..b08f7e152c 100644 --- a/apps/package.json +++ b/apps/package.json @@ -6,10 +6,10 @@ "nativescript": { "id": "org.nativescript.apps", "tns-android": { - "version": "next" + "version": "6.0.0-2019-05-16-172644-03" }, "tns-ios": { - "version": "next" + "version": "6.0.0-2019-05-13-154237-01" } }, "dependencies": { @@ -24,4 +24,4 @@ "tns-platform-declarations": "*", "typescript": "^3.1.6" } -} \ No newline at end of file +} diff --git a/tns-core-modules/ui/gestures/gestures.ios.ts b/tns-core-modules/ui/gestures/gestures.ios.ts index f2753760ae..812f462a92 100644 --- a/tns-core-modules/ui/gestures/gestures.ios.ts +++ b/tns-core-modules/ui/gestures/gestures.ios.ts @@ -8,7 +8,7 @@ import { GesturesObserverBase, toString, TouchAction, GestureStateTypes, Gesture export * from "./gestures-common"; export function observe(target: View, type: GestureTypes, callback: (args: GestureEventData) => void, context?: any): GesturesObserver { - let observer = new GesturesObserver(target, callback, context); + const observer = new GesturesObserver(target, callback, context); observer.observe(type); return observer; } @@ -16,8 +16,24 @@ export function observe(target: View, type: GestureTypes, callback: (args: Gestu class UIGestureRecognizerDelegateImpl extends NSObject implements UIGestureRecognizerDelegate { public static ObjCProtocols = [UIGestureRecognizerDelegate]; public gestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer(gestureRecognizer: UIGestureRecognizer, otherGestureRecognizer: UIGestureRecognizer): boolean { + // If both gesture recognizers are of type UITapGestureRecognizer, do not allow + // simultaneous recognition. + if (gestureRecognizer instanceof UITapGestureRecognizer && otherGestureRecognizer instanceof UITapGestureRecognizer) { + return false; + } return true; } + + public gestureRecognizerShouldRequireFailureOfGestureRecognizer(gestureRecognizer: UIGestureRecognizer, otherGestureRecognizer: UIGestureRecognizer): boolean { + // If both gesture recognizers are of type UITapGestureRecognizer & one of them is a doubleTap, + // we must require a failure. + if (gestureRecognizer instanceof UITapGestureRecognizer + && otherGestureRecognizer instanceof UITapGestureRecognizer + && otherGestureRecognizer.numberOfTapsRequired === 2) { + return true; + } + return false; + } } let recognizerDelegateInstance: UIGestureRecognizerDelegateImpl = UIGestureRecognizerDelegateImpl.new(); @@ -48,12 +64,12 @@ class UIGestureRecognizerImpl extends NSObject { } public recognize(recognizer: UIGestureRecognizer): void { - let owner = this._owner.get(); - let callback = this._callback ? this._callback : (owner ? owner.callback : null); - let typeParam = this._type; - let target = owner ? owner.target : undefined; + const owner = this._owner.get(); + const callback = this._callback ? this._callback : (owner ? owner.callback : null); + const typeParam = this._type; + const target = owner ? owner.target : undefined; - let args = { + const args = { type: typeParam, view: target, ios: recognizer, @@ -82,7 +98,7 @@ export class GesturesObserver extends GesturesObserverBase { public androidOnTouchEvent(motionEvent: android.view.MotionEvent): void { // } - + public observe(type: GestureTypes) { if (this.target) { this.type = type; @@ -106,17 +122,14 @@ export class GesturesObserver extends GesturesObserverBase { this._detach(); if (target && target.nativeViewProtected && target.nativeViewProtected.addGestureRecognizer) { - let nativeView = target.nativeViewProtected; + const nativeView = target.nativeViewProtected; if (type & GestureTypes.tap) { nativeView.addGestureRecognizer(this._createRecognizer(GestureTypes.tap)); } if (type & GestureTypes.doubleTap) { - let r = this._createRecognizer(GestureTypes.doubleTap); - r.numberOfTapsRequired = 2; - - nativeView.addGestureRecognizer(r); + nativeView.addGestureRecognizer(this._createRecognizer(GestureTypes.doubleTap)); } if (type & GestureTypes.pinch) { @@ -203,8 +216,8 @@ export class GesturesObserver extends GesturesObserverBase { private _createRecognizer(type: GestureTypes, callback?: (args: GestureEventData) => void, swipeDirection?: UISwipeGestureRecognizerDirection): UIGestureRecognizer { let recognizer: UIGestureRecognizer; let name = toString(type); - let target = _createUIGestureRecognizerTarget(this, type, callback, this.context); - let recognizerType = _getUIGestureRecognizerType(type); + const target = _createUIGestureRecognizerTarget(this, type, callback, this.context); + const recognizerType = _getUIGestureRecognizerType(type); if (recognizerType) { recognizer = recognizerType.alloc().initWithTargetAction(target, "recognize"); @@ -212,9 +225,10 @@ export class GesturesObserver extends GesturesObserverBase { if (type === GestureTypes.swipe && swipeDirection) { name = name + swipeDirection.toString(); (recognizer).direction = swipeDirection; - } - else if (type === GestureTypes.touch) { + } else if (type === GestureTypes.touch) { (recognizer).observer = this; + } else if (type === GestureTypes.doubleTap) { + (recognizer).numberOfTapsRequired = 2; } if (recognizer) { @@ -486,4 +500,4 @@ class TouchGestureEventData implements TouchGestureEventData { getY(): number { return this.getMainPointer().locationInView(this.view.nativeViewProtected).y } -} \ No newline at end of file +} From c7eca4ec7dbb8e0cc3fa256155145789a8aa9d6a Mon Sep 17 00:00:00 2001 From: lukecurran Date: Sun, 2 Jun 2019 10:58:23 -0500 Subject: [PATCH 2/9] fix(gestures-android): Handle tap and double tap listeners on the same target --- .../ui/gestures/gestures.android.ts | 83 ++++++++++--------- tns-core-modules/ui/gestures/gestures.ios.ts | 3 +- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/tns-core-modules/ui/gestures/gestures.android.ts b/tns-core-modules/ui/gestures/gestures.android.ts index b86f738174..7ffa359f05 100644 --- a/tns-core-modules/ui/gestures/gestures.android.ts +++ b/tns-core-modules/ui/gestures/gestures.android.ts @@ -10,6 +10,8 @@ import { // Import layout from utils directly to avoid circular references import { layout } from "../../utils/utils"; +import * as timer from "../../timer"; + export * from "./gestures-common"; interface TapAndDoubleTapGestureListener { @@ -27,6 +29,11 @@ function initializeTapAndDoubleTapGestureListener() { private _target: View; private _type: number; + private _lastTapTime: number = 0; + private _tapTimeoutId: number; + + private static DoubleTapTimeout = android.view.ViewConfiguration.getDoubleTapTimeout(); + constructor(observer: GesturesObserver, target: View, type: number) { super(); @@ -36,29 +43,40 @@ function initializeTapAndDoubleTapGestureListener() { return global.__native(this); } - public onSingleTapUp(motionEvent: android.view.MotionEvent): boolean { - if (this._type & GestureTypes.tap) { - let args = _getArgs(GestureTypes.tap, this._target, motionEvent); - _executeCallback(this._observer, args); + public onDown(motionEvent: android.view.MotionEvent): boolean { + const tapTime = Date.now(); + if ((tapTime - this._lastTapTime) <= TapAndDoubleTapGestureListenerImpl.DoubleTapTimeout) { + this._handleDoubleTap(motionEvent); + } else { + this._handleSingleTap(motionEvent); } + this._lastTapTime = tapTime; return true; } - public onDoubleTap(motionEvent: android.view.MotionEvent): boolean { - if (this._type & GestureTypes.doubleTap) { - let args = _getArgs(GestureTypes.doubleTap, this._target, motionEvent); + public onLongPress(motionEvent: android.view.MotionEvent): void { + if (this._type & GestureTypes.longPress) { + const args = _getArgs(GestureTypes.longPress, this._target, motionEvent); _executeCallback(this._observer, args); } - return true; } - public onDown(motionEvent: android.view.MotionEvent): boolean { - return true; + private _handleSingleTap(motionEvent: android.view.MotionEvent): void { + this._tapTimeoutId = timer.setTimeout(() => { + if (this._type & GestureTypes.tap) { + const args = _getArgs(GestureTypes.tap, this._target, motionEvent); + _executeCallback(this._observer, args); + } + timer.clearTimeout(this._tapTimeoutId); + }, TapAndDoubleTapGestureListenerImpl.DoubleTapTimeout); } - public onLongPress(motionEvent: android.view.MotionEvent): void { - if (this._type & GestureTypes.longPress) { - let args = _getArgs(GestureTypes.longPress, this._target, motionEvent); + private _handleDoubleTap(motionEvent: android.view.MotionEvent): void { + if (this._tapTimeoutId) { + timer.clearTimeout(this._tapTimeoutId); + } + if (this._type & GestureTypes.doubleTap) { + const args = _getArgs(GestureTypes.doubleTap, this._target, motionEvent); _executeCallback(this._observer, args); } } @@ -94,7 +112,7 @@ function initializePinchGestureListener() { public onScaleBegin(detector: android.view.ScaleGestureDetector): boolean { this._scale = detector.getScaleFactor(); - let args = new PinchGestureEventData( + const args = new PinchGestureEventData( this._target, detector, this._scale, @@ -109,7 +127,7 @@ function initializePinchGestureListener() { public onScale(detector: android.view.ScaleGestureDetector): boolean { this._scale *= detector.getScaleFactor(); - let args = new PinchGestureEventData( + const args = new PinchGestureEventData( this._target, detector, this._scale, @@ -123,7 +141,7 @@ function initializePinchGestureListener() { public onScaleEnd(detector: android.view.ScaleGestureDetector): void { this._scale *= detector.getScaleFactor(); - let args = new PinchGestureEventData( + const args = new PinchGestureEventData( this._target, detector, this._scale, @@ -172,41 +190,28 @@ function initializeSwipeGestureListener() { let deltaX = currentEvent.getX() - initialEvent.getX(); if (Math.abs(deltaX) > Math.abs(deltaY)) { - if (Math.abs(deltaX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) { - if (deltaX > 0) { - args = _getSwipeArgs(SwipeDirection.right, this._target, initialEvent, currentEvent); _executeCallback(this._observer, args); - result = true; } else { - args = _getSwipeArgs(SwipeDirection.left, this._target, initialEvent, currentEvent); _executeCallback(this._observer, args); - result = true; } } - } else { - if (Math.abs(deltaY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) { - if (deltaY > 0) { - args = _getSwipeArgs(SwipeDirection.down, this._target, initialEvent, currentEvent); _executeCallback(this._observer, args); - result = true; } else { - args = _getSwipeArgs(SwipeDirection.up, this._target, initialEvent, currentEvent); _executeCallback(this._observer, args); - result = true; } } @@ -228,7 +233,7 @@ const INVALID_POINTER_ID = -1; const TO_DEGREES = (180 / Math.PI); export function observe(target: View, type: GestureTypes, callback: (args: GestureEventData) => void, context?: any): GesturesObserver { - let observer = new GesturesObserver(target, callback, context); + const observer = new GesturesObserver(target, callback, context); observer.observe(type); return observer; } @@ -292,7 +297,7 @@ export class GesturesObserver extends GesturesObserverBase { private _attach(target: View, type: GestureTypes) { this._detach(); - if (type & GestureTypes.tap || type & GestureTypes.doubleTap || type & GestureTypes.longPress) { + if ((type & GestureTypes.tap) || (type & GestureTypes.doubleTap) || (type & GestureTypes.longPress)) { initializeTapAndDoubleTapGestureListener(); this._simpleGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new TapAndDoubleTapGestureListener(this, this.target, type)); } @@ -465,7 +470,7 @@ class CustomPanGestureDetector { return true; } - private trackStop(currentEvent: android.view.MotionEvent, cahceEvent: boolean) { + private trackStop(currentEvent: android.view.MotionEvent, cacheEvent: boolean) { if (this.isTracking) { let args = _getPanArgs(this.deltaX, this.deltaY, this.target, GestureStateTypes.ended, null, currentEvent); _executeCallback(this.observer, args); @@ -475,10 +480,9 @@ class CustomPanGestureDetector { this.isTracking = false; } - if (cahceEvent) { + if (cacheEvent) { this.lastEventCache = currentEvent; - } - else { + } else { this.lastEventCache = undefined; } } @@ -509,8 +513,7 @@ class CustomPanGestureDetector { x: event.getRawX() / this.density, y: event.getRawY() / this.density }; - } - else { + } else { const offX = event.getRawX() - event.getX(); const offY = event.getRawY() - event.getY(); let res = { x: 0, y: 0 }; @@ -559,8 +562,7 @@ class CustomRotateGestureDetector { if (this.trackedPtrId1 === INVALID_POINTER_ID && pointerID !== this.trackedPtrId2) { this.trackedPtrId1 = pointerID; assigned = true; - } - else if (this.trackedPtrId2 === INVALID_POINTER_ID && pointerID !== this.trackedPtrId1) { + } else if (this.trackedPtrId2 === INVALID_POINTER_ID && pointerID !== this.trackedPtrId1) { this.trackedPtrId2 = pointerID; assigned = true; } @@ -585,8 +587,7 @@ class CustomRotateGestureDetector { case android.view.MotionEvent.ACTION_POINTER_UP: if (pointerID === this.trackedPtrId1) { this.trackedPtrId1 = INVALID_POINTER_ID; - } - else if (pointerID === this.trackedPtrId2) { + } else if (pointerID === this.trackedPtrId2) { this.trackedPtrId2 = INVALID_POINTER_ID; } diff --git a/tns-core-modules/ui/gestures/gestures.ios.ts b/tns-core-modules/ui/gestures/gestures.ios.ts index 812f462a92..192fca0a88 100644 --- a/tns-core-modules/ui/gestures/gestures.ios.ts +++ b/tns-core-modules/ui/gestures/gestures.ios.ts @@ -15,6 +15,7 @@ export function observe(target: View, type: GestureTypes, callback: (args: Gestu class UIGestureRecognizerDelegateImpl extends NSObject implements UIGestureRecognizerDelegate { public static ObjCProtocols = [UIGestureRecognizerDelegate]; + public gestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer(gestureRecognizer: UIGestureRecognizer, otherGestureRecognizer: UIGestureRecognizer): boolean { // If both gesture recognizers are of type UITapGestureRecognizer, do not allow // simultaneous recognition. @@ -48,7 +49,7 @@ class UIGestureRecognizerImpl extends NSObject { private _context: any; public static initWithOwnerTypeCallback(owner: WeakRef, type: any, callback?: Function, thisArg?: any): UIGestureRecognizerImpl { - let handler = UIGestureRecognizerImpl.new(); + const handler = UIGestureRecognizerImpl.new(); handler._owner = owner; handler._type = type; From 4e59f9f26115de971b45ad7d94db420372390c28 Mon Sep 17 00:00:00 2001 From: lukecurran Date: Sun, 2 Jun 2019 11:00:50 -0500 Subject: [PATCH 3/9] refact(iOS): code convention for iOS gestures --- tns-core-modules/ui/gestures/gestures.ios.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tns-core-modules/ui/gestures/gestures.ios.ts b/tns-core-modules/ui/gestures/gestures.ios.ts index 192fca0a88..d0a6a72465 100644 --- a/tns-core-modules/ui/gestures/gestures.ios.ts +++ b/tns-core-modules/ui/gestures/gestures.ios.ts @@ -300,8 +300,8 @@ function _getSwipeDirection(direction: UISwipeGestureRecognizerDirection): Swipe } function _getPinchData(args: GestureEventData): PinchGestureEventData { - let recognizer = args.ios; - let center = recognizer.locationInView(args.view.nativeViewProtected); + const recognizer = args.ios; + const center = recognizer.locationInView(args.view.nativeViewProtected); return { type: args.type, @@ -318,7 +318,7 @@ function _getPinchData(args: GestureEventData): PinchGestureEventData { } function _getSwipeData(args: GestureEventData): SwipeGestureEventData { - let recognizer = args.ios; + const recognizer = args.ios; return { type: args.type, @@ -332,7 +332,8 @@ function _getSwipeData(args: GestureEventData): SwipeGestureEventData { } function _getPanData(args: GestureEventData, view: UIView): PanGestureEventData { - let recognizer = args.ios; + const recognizer = args.ios; + return { type: args.type, view: args.view, @@ -347,7 +348,8 @@ function _getPanData(args: GestureEventData, view: UIView): PanGestureEventData } function _getRotationData(args: GestureEventData): RotationGestureEventData { - let recognizer = args.ios; + const recognizer = args.ios; + return { type: args.type, view: args.view, @@ -409,6 +411,7 @@ class Pointer implements Pointer { private _view: View; private _location: CGPoint; + private get location(): CGPoint { if (!this._location) { this._location = this.ios.locationInView(this._view.nativeViewProtected); From 8f513ee5f4e0157decad36114ae7e21a210d89e8 Mon Sep 17 00:00:00 2001 From: lukecurran Date: Sun, 2 Jun 2019 11:07:06 -0500 Subject: [PATCH 4/9] Reset tns- for test app --- apps/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/package.json b/apps/package.json index b08f7e152c..42718b4c0f 100644 --- a/apps/package.json +++ b/apps/package.json @@ -6,10 +6,10 @@ "nativescript": { "id": "org.nativescript.apps", "tns-android": { - "version": "6.0.0-2019-05-16-172644-03" + "version": "next" }, "tns-ios": { - "version": "6.0.0-2019-05-13-154237-01" + "version": "next" } }, "dependencies": { From 6c7cbdd5483083d777f1f38341a34fe49478966c Mon Sep 17 00:00:00 2001 From: lukecurran Date: Thu, 23 May 2019 09:08:00 -0500 Subject: [PATCH 5/9] Fix simultaneous tap gestures for iOS --- apps/app/ui-tests-app/events/gestures.ts | 59 +++++++++++++------- apps/package.json | 6 +- tns-core-modules/ui/gestures/gestures.ios.ts | 48 ++++++++++------ 3 files changed, 74 insertions(+), 39 deletions(-) diff --git a/apps/app/ui-tests-app/events/gestures.ts b/apps/app/ui-tests-app/events/gestures.ts index 264106db22..f378b443aa 100644 --- a/apps/app/ui-tests-app/events/gestures.ts +++ b/apps/app/ui-tests-app/events/gestures.ts @@ -7,43 +7,49 @@ import * as stackLayoutModule from "tns-core-modules/ui/layouts/stack-layout"; export function createPage() { - var stack = new stackLayoutModule.StackLayout(); - var labelHeight = Math.round(deviceProperties.screen.mainScreen.heightPixels / (7 * deviceProperties.screen.mainScreen.scale)); - var stopButton = new button.Button(); + const stack = new stackLayoutModule.StackLayout(); + const labelHeight = Math.round(deviceProperties.screen.mainScreen.heightPixels / (7 * deviceProperties.screen.mainScreen.scale)); + const stopButton = new button.Button(); stopButton.text = "Stop Detecting Gestures"; stack.addChild(stopButton); - var tapLabel = new labelModule.Label(); + const tapLabel = new labelModule.Label(); tapLabel.text = "Tap here"; stack.addChild(tapLabel); - var doubletapLabel = new labelModule.Label(); + const doubletapLabel = new labelModule.Label(); doubletapLabel.text = "Double Tap here"; stack.addChild(doubletapLabel); - var longpressLabel = new labelModule.Label(); + const longpressLabel = new labelModule.Label(); longpressLabel.text = "Long Press here"; stack.addChild(longpressLabel); - var swipeLabel = new labelModule.Label(); + const tapAndDoubleTapLabel = new labelModule.Label(); + tapAndDoubleTapLabel.height = labelHeight; + tapAndDoubleTapLabel.text = "Tap or Double Tap"; + tapAndDoubleTapLabel.textWrap = true; + stack.addChild(tapAndDoubleTapLabel); + + const swipeLabel = new labelModule.Label(); swipeLabel.height = labelHeight; swipeLabel.text = "Swipe here"; swipeLabel.textWrap = true; stack.addChild(swipeLabel); - var panLabel = new labelModule.Label(); + const panLabel = new labelModule.Label(); panLabel.height = labelHeight; panLabel.text = "Pan here"; panLabel.textWrap = true; stack.addChild(panLabel); - var pinchLabel = new labelModule.Label(); + const pinchLabel = new labelModule.Label(); pinchLabel.height = labelHeight; pinchLabel.text = "Pinch here"; pinchLabel.textWrap = true; stack.addChild(pinchLabel); - var rotaionLabel = new labelModule.Label(); + const rotaionLabel = new labelModule.Label(); rotaionLabel.height = labelHeight; rotaionLabel.text = "Rotate here"; rotaionLabel.textWrap = true; @@ -57,6 +63,8 @@ export function createPage() { observer5.disconnect(); observer6.disconnect(); observer7.disconnect(); + observer8.disconnect(); + observer9.disconnect(); tapLabel.text = "Gestures detection disabled"; doubletapLabel.text = "Gestures detection disabled"; longpressLabel.text = "Gestures detection disabled"; @@ -64,56 +72,69 @@ export function createPage() { panLabel.text = "Gestures detection disabled"; pinchLabel.text = "Gestures detection disabled"; rotaionLabel.text = "Gestures detection disabled"; + tapAndDoubleTapLabel.text = "Gestures detection disabled"; }); tapLabel.on(gestures.GestureTypes.tap, function (args: gestures.GestureEventData) { tapLabel.text = "Tap gesture detected, " + (args.object === tapLabel); }); - var observer1 = tapLabel.getGestureObservers(gestures.GestureTypes.tap)[0]; + const observer1 = tapLabel.getGestureObservers(gestures.GestureTypes.tap)[0]; doubletapLabel.on(gestures.GestureTypes.doubleTap, function (args: gestures.GestureEventData) { doubletapLabel.text = "Double Tap gesture detected, " + (args.object === doubletapLabel); }); - var observer2 = doubletapLabel.getGestureObservers(gestures.GestureTypes.doubleTap)[0]; + const observer2 = doubletapLabel.getGestureObservers(gestures.GestureTypes.doubleTap)[0]; longpressLabel.on(gestures.GestureTypes.longPress, function (args: gestures.GestureEventData) { longpressLabel.text = "Long Press gesture detected, " + (args.object === longpressLabel); }); - var observer3 = longpressLabel.getGestureObservers(gestures.GestureTypes.longPress)[0]; + const observer3 = longpressLabel.getGestureObservers(gestures.GestureTypes.longPress)[0]; swipeLabel.on(gestures.GestureTypes.swipe, function (args: gestures.SwipeGestureEventData) { swipeLabel.text = "Swipe Direction: " + args.direction + ", " + (args.object === swipeLabel); // + getStateAsString(args.state); }); - var observer4 = swipeLabel.getGestureObservers(gestures.GestureTypes.swipe)[0]; + const observer4 = swipeLabel.getGestureObservers(gestures.GestureTypes.swipe)[0]; panLabel.on(gestures.GestureTypes.pan, function (args: gestures.PanGestureEventData) { panLabel.text = "Pan deltaX:" + Math.round(args.deltaX) + "; deltaY:" + Math.round(args.deltaY) + ";" + ", " + (args.object === panLabel) + getStateAsString(args.state); }); - var observer5 = panLabel.getGestureObservers(gestures.GestureTypes.pan)[0]; + const observer5 = panLabel.getGestureObservers(gestures.GestureTypes.pan)[0]; pinchLabel.on(gestures.GestureTypes.pinch, function (args: gestures.PinchGestureEventData) { pinchLabel.text = "Pinch Scale: " + Math.round(args.scale) + ", " + (args.object === pinchLabel) + getStateAsString(args.state); }); - var observer6 = pinchLabel.getGestureObservers(gestures.GestureTypes.pinch)[0]; + const observer6 = pinchLabel.getGestureObservers(gestures.GestureTypes.pinch)[0]; rotaionLabel.on(gestures.GestureTypes.rotation, function (args: gestures.RotationGestureEventData) { rotaionLabel.text = "Rotation: " + Math.round(args.rotation) + ", " + (args.object === rotaionLabel) + getStateAsString(args.state); }); - var observer7 = rotaionLabel.getGestureObservers(gestures.GestureTypes.rotation)[0]; + const observer7 = rotaionLabel.getGestureObservers(gestures.GestureTypes.rotation)[0]; + + tapAndDoubleTapLabel.on(gestures.GestureTypes.doubleTap, function (args: gestures.GestureEventData) { + tapAndDoubleTapLabel.text = "Last action: Double tap gesture, " + (args.object === tapAndDoubleTapLabel); + }); + + const observer8 = tapAndDoubleTapLabel.getGestureObservers(gestures.GestureTypes.doubleTap)[0]; + + tapAndDoubleTapLabel.on(gestures.GestureTypes.tap, function (args: gestures.GestureEventData) { + tapAndDoubleTapLabel.text = "Last action: Tap gesture, " + (args.object === tapAndDoubleTapLabel); + }); + + const observer9 = tapAndDoubleTapLabel.getGestureObservers(gestures.GestureTypes.tap)[0]; - var page = new pages.Page(); + const page = new pages.Page(); page.content = stack; return page; } -var states = new Array(); +const states = new Array(); function getStateAsString(state: gestures.GestureStateTypes): string { if (state === gestures.GestureStateTypes.began) { states.length = 0; diff --git a/apps/package.json b/apps/package.json index a548304ff2..b08f7e152c 100644 --- a/apps/package.json +++ b/apps/package.json @@ -6,10 +6,10 @@ "nativescript": { "id": "org.nativescript.apps", "tns-android": { - "version": "next" + "version": "6.0.0-2019-05-16-172644-03" }, "tns-ios": { - "version": "next" + "version": "6.0.0-2019-05-13-154237-01" } }, "dependencies": { @@ -24,4 +24,4 @@ "tns-platform-declarations": "*", "typescript": "^3.1.6" } -} \ No newline at end of file +} diff --git a/tns-core-modules/ui/gestures/gestures.ios.ts b/tns-core-modules/ui/gestures/gestures.ios.ts index f2753760ae..812f462a92 100644 --- a/tns-core-modules/ui/gestures/gestures.ios.ts +++ b/tns-core-modules/ui/gestures/gestures.ios.ts @@ -8,7 +8,7 @@ import { GesturesObserverBase, toString, TouchAction, GestureStateTypes, Gesture export * from "./gestures-common"; export function observe(target: View, type: GestureTypes, callback: (args: GestureEventData) => void, context?: any): GesturesObserver { - let observer = new GesturesObserver(target, callback, context); + const observer = new GesturesObserver(target, callback, context); observer.observe(type); return observer; } @@ -16,8 +16,24 @@ export function observe(target: View, type: GestureTypes, callback: (args: Gestu class UIGestureRecognizerDelegateImpl extends NSObject implements UIGestureRecognizerDelegate { public static ObjCProtocols = [UIGestureRecognizerDelegate]; public gestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer(gestureRecognizer: UIGestureRecognizer, otherGestureRecognizer: UIGestureRecognizer): boolean { + // If both gesture recognizers are of type UITapGestureRecognizer, do not allow + // simultaneous recognition. + if (gestureRecognizer instanceof UITapGestureRecognizer && otherGestureRecognizer instanceof UITapGestureRecognizer) { + return false; + } return true; } + + public gestureRecognizerShouldRequireFailureOfGestureRecognizer(gestureRecognizer: UIGestureRecognizer, otherGestureRecognizer: UIGestureRecognizer): boolean { + // If both gesture recognizers are of type UITapGestureRecognizer & one of them is a doubleTap, + // we must require a failure. + if (gestureRecognizer instanceof UITapGestureRecognizer + && otherGestureRecognizer instanceof UITapGestureRecognizer + && otherGestureRecognizer.numberOfTapsRequired === 2) { + return true; + } + return false; + } } let recognizerDelegateInstance: UIGestureRecognizerDelegateImpl = UIGestureRecognizerDelegateImpl.new(); @@ -48,12 +64,12 @@ class UIGestureRecognizerImpl extends NSObject { } public recognize(recognizer: UIGestureRecognizer): void { - let owner = this._owner.get(); - let callback = this._callback ? this._callback : (owner ? owner.callback : null); - let typeParam = this._type; - let target = owner ? owner.target : undefined; + const owner = this._owner.get(); + const callback = this._callback ? this._callback : (owner ? owner.callback : null); + const typeParam = this._type; + const target = owner ? owner.target : undefined; - let args = { + const args = { type: typeParam, view: target, ios: recognizer, @@ -82,7 +98,7 @@ export class GesturesObserver extends GesturesObserverBase { public androidOnTouchEvent(motionEvent: android.view.MotionEvent): void { // } - + public observe(type: GestureTypes) { if (this.target) { this.type = type; @@ -106,17 +122,14 @@ export class GesturesObserver extends GesturesObserverBase { this._detach(); if (target && target.nativeViewProtected && target.nativeViewProtected.addGestureRecognizer) { - let nativeView = target.nativeViewProtected; + const nativeView = target.nativeViewProtected; if (type & GestureTypes.tap) { nativeView.addGestureRecognizer(this._createRecognizer(GestureTypes.tap)); } if (type & GestureTypes.doubleTap) { - let r = this._createRecognizer(GestureTypes.doubleTap); - r.numberOfTapsRequired = 2; - - nativeView.addGestureRecognizer(r); + nativeView.addGestureRecognizer(this._createRecognizer(GestureTypes.doubleTap)); } if (type & GestureTypes.pinch) { @@ -203,8 +216,8 @@ export class GesturesObserver extends GesturesObserverBase { private _createRecognizer(type: GestureTypes, callback?: (args: GestureEventData) => void, swipeDirection?: UISwipeGestureRecognizerDirection): UIGestureRecognizer { let recognizer: UIGestureRecognizer; let name = toString(type); - let target = _createUIGestureRecognizerTarget(this, type, callback, this.context); - let recognizerType = _getUIGestureRecognizerType(type); + const target = _createUIGestureRecognizerTarget(this, type, callback, this.context); + const recognizerType = _getUIGestureRecognizerType(type); if (recognizerType) { recognizer = recognizerType.alloc().initWithTargetAction(target, "recognize"); @@ -212,9 +225,10 @@ export class GesturesObserver extends GesturesObserverBase { if (type === GestureTypes.swipe && swipeDirection) { name = name + swipeDirection.toString(); (recognizer).direction = swipeDirection; - } - else if (type === GestureTypes.touch) { + } else if (type === GestureTypes.touch) { (recognizer).observer = this; + } else if (type === GestureTypes.doubleTap) { + (recognizer).numberOfTapsRequired = 2; } if (recognizer) { @@ -486,4 +500,4 @@ class TouchGestureEventData implements TouchGestureEventData { getY(): number { return this.getMainPointer().locationInView(this.view.nativeViewProtected).y } -} \ No newline at end of file +} From 71ff3501a838e6f65fbb0ec2f6bb487a19023529 Mon Sep 17 00:00:00 2001 From: lukecurran Date: Sun, 2 Jun 2019 10:58:23 -0500 Subject: [PATCH 6/9] fix(gestures-android): Handle tap and double tap listeners on the same target --- .../ui/gestures/gestures.android.ts | 83 ++++++++++--------- tns-core-modules/ui/gestures/gestures.ios.ts | 3 +- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/tns-core-modules/ui/gestures/gestures.android.ts b/tns-core-modules/ui/gestures/gestures.android.ts index b86f738174..b576390399 100644 --- a/tns-core-modules/ui/gestures/gestures.android.ts +++ b/tns-core-modules/ui/gestures/gestures.android.ts @@ -10,6 +10,8 @@ import { // Import layout from utils directly to avoid circular references import { layout } from "../../utils/utils"; +import * as timer from "../../timer"; + export * from "./gestures-common"; interface TapAndDoubleTapGestureListener { @@ -27,6 +29,11 @@ function initializeTapAndDoubleTapGestureListener() { private _target: View; private _type: number; + private _lastTapTime: number = 0; + private _tapTimeoutId: number; + + private static DoubleTapTimeout = android.view.ViewConfiguration.getDoubleTapTimeout(); + constructor(observer: GesturesObserver, target: View, type: number) { super(); @@ -36,29 +43,40 @@ function initializeTapAndDoubleTapGestureListener() { return global.__native(this); } - public onSingleTapUp(motionEvent: android.view.MotionEvent): boolean { - if (this._type & GestureTypes.tap) { - let args = _getArgs(GestureTypes.tap, this._target, motionEvent); - _executeCallback(this._observer, args); + public onDown(motionEvent: android.view.MotionEvent): boolean { + const tapTime = Date.now(); + if ((tapTime - this._lastTapTime) <= TapAndDoubleTapGestureListenerImpl.DoubleTapTimeout) { + this._handleDoubleTap(motionEvent); + } else { + this._handleSingleTap(motionEvent); } + this._lastTapTime = tapTime; return true; } - public onDoubleTap(motionEvent: android.view.MotionEvent): boolean { - if (this._type & GestureTypes.doubleTap) { - let args = _getArgs(GestureTypes.doubleTap, this._target, motionEvent); + public onLongPress(motionEvent: android.view.MotionEvent): void { + if (this._type & GestureTypes.longPress) { + const args = _getArgs(GestureTypes.longPress, this._target, motionEvent); _executeCallback(this._observer, args); } - return true; } - public onDown(motionEvent: android.view.MotionEvent): boolean { - return true; + private _handleSingleTap(motionEvent: android.view.MotionEvent): void { + this._tapTimeoutId = timer.setTimeout(() => { + if (this._type & GestureTypes.tap) { + const args = _getArgs(GestureTypes.tap, this._target, motionEvent); + _executeCallback(this._observer, args); + } + timer.clearTimeout(this._tapTimeoutId); + }, TapAndDoubleTapGestureListenerImpl.DoubleTapTimeout); } - public onLongPress(motionEvent: android.view.MotionEvent): void { - if (this._type & GestureTypes.longPress) { - let args = _getArgs(GestureTypes.longPress, this._target, motionEvent); + private _handleDoubleTap(motionEvent: android.view.MotionEvent): void { + if (this._tapTimeoutId) { + timer.clearTimeout(this._tapTimeoutId); + } + if (this._type & GestureTypes.doubleTap) { + const args = _getArgs(GestureTypes.doubleTap, this._target, motionEvent); _executeCallback(this._observer, args); } } @@ -94,7 +112,7 @@ function initializePinchGestureListener() { public onScaleBegin(detector: android.view.ScaleGestureDetector): boolean { this._scale = detector.getScaleFactor(); - let args = new PinchGestureEventData( + const args = new PinchGestureEventData( this._target, detector, this._scale, @@ -109,7 +127,7 @@ function initializePinchGestureListener() { public onScale(detector: android.view.ScaleGestureDetector): boolean { this._scale *= detector.getScaleFactor(); - let args = new PinchGestureEventData( + const args = new PinchGestureEventData( this._target, detector, this._scale, @@ -123,7 +141,7 @@ function initializePinchGestureListener() { public onScaleEnd(detector: android.view.ScaleGestureDetector): void { this._scale *= detector.getScaleFactor(); - let args = new PinchGestureEventData( + const args = new PinchGestureEventData( this._target, detector, this._scale, @@ -172,41 +190,28 @@ function initializeSwipeGestureListener() { let deltaX = currentEvent.getX() - initialEvent.getX(); if (Math.abs(deltaX) > Math.abs(deltaY)) { - if (Math.abs(deltaX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) { - if (deltaX > 0) { - args = _getSwipeArgs(SwipeDirection.right, this._target, initialEvent, currentEvent); _executeCallback(this._observer, args); - result = true; } else { - args = _getSwipeArgs(SwipeDirection.left, this._target, initialEvent, currentEvent); _executeCallback(this._observer, args); - result = true; } } - } else { - if (Math.abs(deltaY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) { - if (deltaY > 0) { - args = _getSwipeArgs(SwipeDirection.down, this._target, initialEvent, currentEvent); _executeCallback(this._observer, args); - result = true; } else { - args = _getSwipeArgs(SwipeDirection.up, this._target, initialEvent, currentEvent); _executeCallback(this._observer, args); - result = true; } } @@ -228,7 +233,7 @@ const INVALID_POINTER_ID = -1; const TO_DEGREES = (180 / Math.PI); export function observe(target: View, type: GestureTypes, callback: (args: GestureEventData) => void, context?: any): GesturesObserver { - let observer = new GesturesObserver(target, callback, context); + const observer = new GesturesObserver(target, callback, context); observer.observe(type); return observer; } @@ -292,7 +297,7 @@ export class GesturesObserver extends GesturesObserverBase { private _attach(target: View, type: GestureTypes) { this._detach(); - if (type & GestureTypes.tap || type & GestureTypes.doubleTap || type & GestureTypes.longPress) { + if ((type & GestureTypes.tap) || (type & GestureTypes.doubleTap) || (type & GestureTypes.longPress)) { initializeTapAndDoubleTapGestureListener(); this._simpleGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new TapAndDoubleTapGestureListener(this, this.target, type)); } @@ -465,7 +470,7 @@ class CustomPanGestureDetector { return true; } - private trackStop(currentEvent: android.view.MotionEvent, cahceEvent: boolean) { + private trackStop(currentEvent: android.view.MotionEvent, cacheEvent: boolean) { if (this.isTracking) { let args = _getPanArgs(this.deltaX, this.deltaY, this.target, GestureStateTypes.ended, null, currentEvent); _executeCallback(this.observer, args); @@ -475,10 +480,9 @@ class CustomPanGestureDetector { this.isTracking = false; } - if (cahceEvent) { + if (cacheEvent) { this.lastEventCache = currentEvent; - } - else { + } else { this.lastEventCache = undefined; } } @@ -509,8 +513,7 @@ class CustomPanGestureDetector { x: event.getRawX() / this.density, y: event.getRawY() / this.density }; - } - else { + } else { const offX = event.getRawX() - event.getX(); const offY = event.getRawY() - event.getY(); let res = { x: 0, y: 0 }; @@ -559,8 +562,7 @@ class CustomRotateGestureDetector { if (this.trackedPtrId1 === INVALID_POINTER_ID && pointerID !== this.trackedPtrId2) { this.trackedPtrId1 = pointerID; assigned = true; - } - else if (this.trackedPtrId2 === INVALID_POINTER_ID && pointerID !== this.trackedPtrId1) { + } else if (this.trackedPtrId2 === INVALID_POINTER_ID && pointerID !== this.trackedPtrId1) { this.trackedPtrId2 = pointerID; assigned = true; } @@ -585,8 +587,7 @@ class CustomRotateGestureDetector { case android.view.MotionEvent.ACTION_POINTER_UP: if (pointerID === this.trackedPtrId1) { this.trackedPtrId1 = INVALID_POINTER_ID; - } - else if (pointerID === this.trackedPtrId2) { + } else if (pointerID === this.trackedPtrId2) { this.trackedPtrId2 = INVALID_POINTER_ID; } diff --git a/tns-core-modules/ui/gestures/gestures.ios.ts b/tns-core-modules/ui/gestures/gestures.ios.ts index 812f462a92..192fca0a88 100644 --- a/tns-core-modules/ui/gestures/gestures.ios.ts +++ b/tns-core-modules/ui/gestures/gestures.ios.ts @@ -15,6 +15,7 @@ export function observe(target: View, type: GestureTypes, callback: (args: Gestu class UIGestureRecognizerDelegateImpl extends NSObject implements UIGestureRecognizerDelegate { public static ObjCProtocols = [UIGestureRecognizerDelegate]; + public gestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer(gestureRecognizer: UIGestureRecognizer, otherGestureRecognizer: UIGestureRecognizer): boolean { // If both gesture recognizers are of type UITapGestureRecognizer, do not allow // simultaneous recognition. @@ -48,7 +49,7 @@ class UIGestureRecognizerImpl extends NSObject { private _context: any; public static initWithOwnerTypeCallback(owner: WeakRef, type: any, callback?: Function, thisArg?: any): UIGestureRecognizerImpl { - let handler = UIGestureRecognizerImpl.new(); + const handler = UIGestureRecognizerImpl.new(); handler._owner = owner; handler._type = type; From 3e6588b230ea89156618413f52631cb793fd63e8 Mon Sep 17 00:00:00 2001 From: lukecurran Date: Sun, 2 Jun 2019 11:00:50 -0500 Subject: [PATCH 7/9] refact(iOS): code convention for iOS gestures --- tns-core-modules/ui/gestures/gestures.ios.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tns-core-modules/ui/gestures/gestures.ios.ts b/tns-core-modules/ui/gestures/gestures.ios.ts index 192fca0a88..d0a6a72465 100644 --- a/tns-core-modules/ui/gestures/gestures.ios.ts +++ b/tns-core-modules/ui/gestures/gestures.ios.ts @@ -300,8 +300,8 @@ function _getSwipeDirection(direction: UISwipeGestureRecognizerDirection): Swipe } function _getPinchData(args: GestureEventData): PinchGestureEventData { - let recognizer = args.ios; - let center = recognizer.locationInView(args.view.nativeViewProtected); + const recognizer = args.ios; + const center = recognizer.locationInView(args.view.nativeViewProtected); return { type: args.type, @@ -318,7 +318,7 @@ function _getPinchData(args: GestureEventData): PinchGestureEventData { } function _getSwipeData(args: GestureEventData): SwipeGestureEventData { - let recognizer = args.ios; + const recognizer = args.ios; return { type: args.type, @@ -332,7 +332,8 @@ function _getSwipeData(args: GestureEventData): SwipeGestureEventData { } function _getPanData(args: GestureEventData, view: UIView): PanGestureEventData { - let recognizer = args.ios; + const recognizer = args.ios; + return { type: args.type, view: args.view, @@ -347,7 +348,8 @@ function _getPanData(args: GestureEventData, view: UIView): PanGestureEventData } function _getRotationData(args: GestureEventData): RotationGestureEventData { - let recognizer = args.ios; + const recognizer = args.ios; + return { type: args.type, view: args.view, @@ -409,6 +411,7 @@ class Pointer implements Pointer { private _view: View; private _location: CGPoint; + private get location(): CGPoint { if (!this._location) { this._location = this.ios.locationInView(this._view.nativeViewProtected); From 3c311857d336353f9000c133c6bfd063d52929f9 Mon Sep 17 00:00:00 2001 From: lukecurran Date: Sun, 2 Jun 2019 11:07:06 -0500 Subject: [PATCH 8/9] Reset tns- for test app --- apps/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/package.json b/apps/package.json index b08f7e152c..42718b4c0f 100644 --- a/apps/package.json +++ b/apps/package.json @@ -6,10 +6,10 @@ "nativescript": { "id": "org.nativescript.apps", "tns-android": { - "version": "6.0.0-2019-05-16-172644-03" + "version": "next" }, "tns-ios": { - "version": "6.0.0-2019-05-13-154237-01" + "version": "next" } }, "dependencies": { From 0f5b87e96597ccfe52dca76301797cdf74a0964c Mon Sep 17 00:00:00 2001 From: lukecurran Date: Mon, 10 Jun 2019 09:18:04 -0500 Subject: [PATCH 9/9] refactor(android): handle single tap on up and double tap between first event up and second event on down --- tns-core-modules/ui/gestures/gestures.android.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tns-core-modules/ui/gestures/gestures.android.ts b/tns-core-modules/ui/gestures/gestures.android.ts index 7ffa359f05..51e5d925a7 100644 --- a/tns-core-modules/ui/gestures/gestures.android.ts +++ b/tns-core-modules/ui/gestures/gestures.android.ts @@ -29,9 +29,9 @@ function initializeTapAndDoubleTapGestureListener() { private _target: View; private _type: number; - private _lastTapTime: number = 0; + private _lastUpTime: number = 0; private _tapTimeoutId: number; - + private static DoubleTapTimeout = android.view.ViewConfiguration.getDoubleTapTimeout(); constructor(observer: GesturesObserver, target: View, type: number) { @@ -43,14 +43,17 @@ function initializeTapAndDoubleTapGestureListener() { return global.__native(this); } + public onSingleTapUp(motionEvent: android.view.MotionEvent): boolean { + this._handleSingleTap(motionEvent); + this._lastUpTime = Date.now(); + return true; + } + public onDown(motionEvent: android.view.MotionEvent): boolean { const tapTime = Date.now(); - if ((tapTime - this._lastTapTime) <= TapAndDoubleTapGestureListenerImpl.DoubleTapTimeout) { + if ((tapTime - this._lastUpTime) <= TapAndDoubleTapGestureListenerImpl.DoubleTapTimeout) { this._handleDoubleTap(motionEvent); - } else { - this._handleSingleTap(motionEvent); } - this._lastTapTime = tapTime; return true; }