From 28665f5594924f174bb58ffda01b972d8090ba85 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Thu, 6 Jan 2022 11:02:17 -0800 Subject: [PATCH] feat(gestures): GestureEvents.gestureAttached added to modify native recognizers when needed --- packages/core/ui/gestures/gestures-common.ts | 4 ++++ packages/core/ui/gestures/index.android.ts | 22 ++++++++++++++------ packages/core/ui/gestures/index.d.ts | 11 ++++++++++ packages/core/ui/gestures/index.ios.ts | 12 +++++++++-- packages/core/ui/index.ts | 2 +- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/packages/core/ui/gestures/gestures-common.ts b/packages/core/ui/gestures/gestures-common.ts index 5ccae2945..cbc8db93b 100644 --- a/packages/core/ui/gestures/gestures-common.ts +++ b/packages/core/ui/gestures/gestures-common.ts @@ -1,6 +1,10 @@ import { GestureEventData, GesturesObserver as GesturesObserverDefinition } from '.'; import { View } from '../core/view'; +export enum GestureEvents { + gestureAttached = 'gestureAttached', +} + export enum GestureTypes { tap = 1 << 0, doubleTap = 1 << 1, diff --git a/packages/core/ui/gestures/index.android.ts b/packages/core/ui/gestures/index.android.ts index 071f16d5b..dba17dded 100644 --- a/packages/core/ui/gestures/index.android.ts +++ b/packages/core/ui/gestures/index.android.ts @@ -4,7 +4,7 @@ import { View } from '../core/view'; import { EventData } from '../../data/observable'; // Types. -import { GesturesObserverBase, toString, TouchAction, GestureStateTypes, GestureTypes, SwipeDirection } from './gestures-common'; +import { GesturesObserverBase, toString, TouchAction, GestureStateTypes, GestureTypes, SwipeDirection, GestureEvents } from './gestures-common'; // Import layout from utils directly to avoid circular references import { layout } from '../../utils'; @@ -297,31 +297,41 @@ export class GesturesObserver extends GesturesObserverBase { private _attach(target: View, type: GestureTypes) { this._detach(); + let recognizer; + if (type & GestureTypes.tap || type & GestureTypes.doubleTap || type & GestureTypes.longPress) { initializeTapAndDoubleTapGestureListener(); - this._simpleGestureDetector = new androidx.core.view.GestureDetectorCompat(target._context, new TapAndDoubleTapGestureListener(this, this.target, type)); + recognizer = this._simpleGestureDetector = new androidx.core.view.GestureDetectorCompat(target._context, new TapAndDoubleTapGestureListener(this, this.target, type)); } if (type & GestureTypes.pinch) { initializePinchGestureListener(); - this._scaleGestureDetector = new android.view.ScaleGestureDetector(target._context, new PinchGestureListener(this, this.target)); + recognizer = this._scaleGestureDetector = new android.view.ScaleGestureDetector(target._context, new PinchGestureListener(this, this.target)); } if (type & GestureTypes.swipe) { initializeSwipeGestureListener(); - this._swipeGestureDetector = new androidx.core.view.GestureDetectorCompat(target._context, new SwipeGestureListener(this, this.target)); + recognizer = this._swipeGestureDetector = new androidx.core.view.GestureDetectorCompat(target._context, new SwipeGestureListener(this, this.target)); } if (type & GestureTypes.pan) { - this._panGestureDetector = new CustomPanGestureDetector(this, this.target); + recognizer = this._panGestureDetector = new CustomPanGestureDetector(this, this.target); } if (type & GestureTypes.rotation) { - this._rotateGestureDetector = new CustomRotateGestureDetector(this, this.target); + recognizer = this._rotateGestureDetector = new CustomRotateGestureDetector(this, this.target); } if (type & GestureTypes.touch) { this._notifyTouch = true; + } else { + this.target.notify({ + eventName: GestureEvents.gestureAttached, + object: this.target, + type, + view: this.target, + ios: recognizer, + }); } } diff --git a/packages/core/ui/gestures/index.d.ts b/packages/core/ui/gestures/index.d.ts index 8cb4e7066..1de495feb 100644 --- a/packages/core/ui/gestures/index.d.ts +++ b/packages/core/ui/gestures/index.d.ts @@ -1,6 +1,17 @@ import { View } from '../core/view'; import { EventData } from '../../data/observable'; +/** + * Events emitted during gesture lifecycle + */ +export enum GestureEvents { + /** + * When the gesture is attached to the view + * Provides access to the native gesture recognizer for further customization + */ + gestureAttached = 'gestureAttached', +} + /** * Defines an enum with supported gesture types. */ diff --git a/packages/core/ui/gestures/index.ios.ts b/packages/core/ui/gestures/index.ios.ts index 7042e99bc..ec6ae4ce8 100644 --- a/packages/core/ui/gestures/index.ios.ts +++ b/packages/core/ui/gestures/index.ios.ts @@ -5,7 +5,7 @@ import { View } from '../core/view'; import { EventData } from '../../data/observable'; // Types. -import { GesturesObserverBase, toString, TouchAction, GestureStateTypes, GestureTypes, SwipeDirection } from './gestures-common'; +import { GesturesObserverBase, toString, TouchAction, GestureStateTypes, GestureTypes, SwipeDirection, GestureEvents } from './gestures-common'; // Import layout from utils directly to avoid circular references import { layout } from '../../utils'; @@ -306,6 +306,14 @@ export class GesturesObserver extends GesturesObserverBase { target: target, }; } + + this.target.notify({ + eventName: GestureEvents.gestureAttached, + object: this.target, + type, + view: this.target, + ios: recognizer, + }); } return recognizer; @@ -348,7 +356,7 @@ function _getUIGestureRecognizerType(type: GestureTypes): any { function getState(recognizer: UIGestureRecognizer) { if (recognizer.state === UIGestureRecognizerState.Began) { return GestureStateTypes.began; - } else if (recognizer.state === UIGestureRecognizerState.Cancelled) { + } else if (recognizer.state === UIGestureRecognizerState.Cancelled || recognizer.state === UIGestureRecognizerState.Failed) { return GestureStateTypes.cancelled; } else if (recognizer.state === UIGestureRecognizerState.Changed) { return GestureStateTypes.changed; diff --git a/packages/core/ui/index.ts b/packages/core/ui/index.ts index 727ee500e..5206d4f52 100644 --- a/packages/core/ui/index.ts +++ b/packages/core/ui/index.ts @@ -27,7 +27,7 @@ export * from './editable-text-base'; export { Frame, setActivityCallbacks } from './frame'; export type { NavigationEntry, NavigationContext, NavigationTransition, BackstackEntry, ViewEntry, AndroidActivityCallbacks } from './frame'; -export { GesturesObserver, TouchAction, GestureTypes, GestureStateTypes, SwipeDirection } from './gestures'; +export { GesturesObserver, TouchAction, GestureTypes, GestureStateTypes, SwipeDirection, GestureEvents } from './gestures'; export type { GestureEventData, GestureEventDataWithState, TapGestureEventData, PanGestureEventData, PinchGestureEventData, RotationGestureEventData, SwipeGestureEventData, TouchGestureEventData } from './gestures'; export { HtmlView } from './html-view';