Skip to content

Commit f838f11

Browse files
author
Nedyalko Nikolov
committed
Refactored gestures to support more scenarios in android.
1 parent 0cb7023 commit f838f11

File tree

9 files changed

+144
-73
lines changed

9 files changed

+144
-73
lines changed

apps/tests/app/testPage.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
import frame = require("ui/frame");
2+
import pageModule = require("ui/page");
3+
import textViewModule = require("ui/text-view");
24

35
export function buttonTap(args) {
4-
frame.topmost().goBack();
6+
console.log("tap");
7+
}
8+
9+
export function doubleTap(args) {
10+
console.log("doubleTap");
11+
}
12+
13+
export function checkRecognizers(args) {
14+
var testTextView = <textViewModule.TextView>(page.getViewById("testTextView"));
15+
console.log("testTextView: " + testTextView.ios.gestureRecognizers);
16+
}
17+
18+
var page: pageModule.Page;
19+
20+
export function pageLoaded(args) {
21+
page = <pageModule.Page>args.object;
522
}

apps/tests/app/testPage.xml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1-
<Page xmlns="http://www.nativescript.org/tns.xsd">
2-
<Button text="Back" tap="buttonTap"/>
1+
<Page xmlns="http://www.nativescript.org/tns.xsd" loaded="pageLoaded">
2+
<StackLayout>
3+
<TextView text="TEST FOR GESTURES" id="testTextView" style="font-size: 50" tap="buttonTap" doubleTap="doubleTap"/>
4+
<Button text="CLICK" tap="checkRecognizers" />
5+
</StackLayout>
36
</Page>

apps/tests/xml-declaration/xml-declaration-tests.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import listViewModule = require("ui/list-view");
1818
import helper = require("../ui/helper");
1919
import viewModule = require("ui/core/view");
2020
import platform = require("platform");
21+
import gesturesModule = require("ui/gestures");
2122

2223
export function test_load_IsDefined() {
2324
TKUnit.assert(types.isFunction(builder.load), "ui/builder should have load method!");
@@ -186,7 +187,7 @@ export function test_parse_ShouldParseBindingsToGestures() {
186187
p.bindingContext = context;
187188
var lbl = <labelModule.Label>p.content;
188189

189-
var observer = (<any>lbl)._gesturesObserver;
190+
var observer = (<any>lbl)._gestureObservers[gesturesModule.GestureTypes.tap][0];
190191

191192
TKUnit.assert(observer !== undefined, "Expected result: true.");
192193
TKUnit.assert(observer._context === context, "Context should be equal to binding context. Actual result: " + observer._context);

ui/core/view-common.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export class View extends proxy.ProxyObject implements definition.View {
132132

133133
public _cssClasses: Array<string> = [];
134134

135-
private _gesturesObserver: gestures.GesturesObserver;
135+
public _gestureObservers = {};
136136
private _updatingInheritedProperties: boolean;
137137

138138
public _options: definition.Options;
@@ -147,9 +147,22 @@ export class View extends proxy.ProxyObject implements definition.View {
147147
this._visualState = visualStateConstants.Normal;
148148
}
149149

150-
observe(type: number, callback: (args: gestures.GestureEventData) => void, thisArg?: any): gestures.GesturesObserver {
151-
this._gesturesObserver = gestures.observe(this, type, callback, thisArg);
152-
return this._gesturesObserver;
150+
observe(type: number, callback: (args: gestures.GestureEventData) => void, thisArg?: any): void {
151+
var gesturesList = this._getGesturesList(type, true);
152+
gesturesList.push(gestures.observe(this, type, callback, thisArg));
153+
}
154+
155+
private _getGesturesList(gestureType: number, createIfNeeded): Array<gestures.GesturesObserver> {
156+
if (!gestureType) {
157+
throw new Error("GestureType must be a valid gesture!");
158+
}
159+
160+
var list = this._gestureObservers[gestureType];
161+
if (!list && createIfNeeded) {
162+
list = [];
163+
this._gestureObservers[gestureType] = list;
164+
}
165+
return list;
153166
}
154167

155168
getViewById<T extends View>(id: string): T {

ui/core/view.android.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import trace = require("trace");
44
import utils = require("utils/utils");
55
import dependencyObservable = require("ui/core/dependency-observable");
66
import proxy = require("ui/core/proxy");
7+
import gestures = require("ui/gestures");
78

89
// merge the exports of the common file with the exports of this file
910
declare var exports;
@@ -77,6 +78,81 @@ export class View extends viewCommon.View {
7778
this._updateOnTouchListener(this.isUserInteractionEnabled);
7879
}
7980

81+
public onLoaded() {
82+
super.onLoaded();
83+
this.setOnTouchListener();
84+
}
85+
86+
public onUnloaded() {
87+
super.onUnloaded();
88+
if (this.android && this.android.setOnTouchListener) {
89+
this.android.setOnTouchListener(null);
90+
}
91+
}
92+
93+
private setOnTouchListener() {
94+
if (this.android && this.android.setOnTouchListener && Object.keys(this._gestureObservers).length > 0) {
95+
var that = new WeakRef(this);
96+
if (this.android.setClickable) {
97+
this.android.setClickable(true);
98+
}
99+
this.android.setOnTouchListener(new android.view.View.OnTouchListener({
100+
onTouch: function (view: android.view.View, motionEvent: android.view.MotionEvent) {
101+
var owner = that.get();
102+
if (!owner) {
103+
return false;
104+
}
105+
var i;
106+
for (var prop in owner._gestureObservers) {
107+
if (owner._gestureObservers.hasOwnProperty(prop)) {
108+
for (i = 0; i < owner._gestureObservers[prop].length; i++) {
109+
var gestureObserver = owner._gestureObservers[prop][i];
110+
if (gestureObserver._simpleGestureDetector) {
111+
gestureObserver._simpleGestureDetector.onTouchEvent(motionEvent);
112+
}
113+
114+
if (gestureObserver._scaleGestureDetector) {
115+
gestureObserver._scaleGestureDetector.onTouchEvent(motionEvent);
116+
}
117+
118+
if (gestureObserver._swipeGestureDetector) {
119+
gestureObserver._swipeGestureDetector.onTouchEvent(motionEvent);
120+
}
121+
122+
if (gestureObserver._panGestureDetector) {
123+
gestureObserver._panGestureDetector.onTouchEvent(motionEvent);
124+
}
125+
126+
if (gestureObserver.type & gestures.GestureTypes.rotation && motionEvent.getPointerCount() === 2) {
127+
128+
var deltaX = motionEvent.getX(0) - motionEvent.getX(1);
129+
var deltaY = motionEvent.getY(0) - motionEvent.getY(1);
130+
var radians = Math.atan(deltaY / deltaX);
131+
var degrees = radians * (180 / Math.PI);
132+
133+
var args = <gestures.RotationGestureEventData>{
134+
type: gestures.GestureTypes.rotation,
135+
view: owner,
136+
android: motionEvent,
137+
rotation: degrees,
138+
ios: null
139+
}
140+
141+
//var observer = that.get();
142+
if (gestureObserver.callback) {
143+
gestureObserver.callback.call(gestureObserver._context, args);
144+
}
145+
146+
}
147+
}
148+
}
149+
}
150+
return owner.android.onTouchEvent(motionEvent);
151+
}
152+
}));
153+
}
154+
}
155+
80156
public _addViewCore(view: viewCommon.View) {
81157
if (this._context) {
82158
view._onAttached(this._context);

ui/core/view.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ declare module "ui/core/view" {
355355
*/
356356
public focus(): boolean;
357357

358-
observe(type: number, callback: (args: gestures.GestureEventData) => void, thisArg?: any): gestures.GesturesObserver;
358+
observe(type: number, callback: (args: gestures.GestureEventData) => void, thisArg?: any);
359359

360360
/**
361361
* A basic method signature to hook an event listener (shortcut alias to the addEventListener method).

ui/gestures/gestures.android.ts

Lines changed: 18 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export class GesturesObserver implements definition.GesturesObserver {
2424

2525
private _onTargetLoaded: (data: observable.EventData) => void;
2626
private _onTargetUnloaded: (data: observable.EventData) => void;
27+
public type: definition.GestureTypes;
2728

2829
constructor(callback: (args: definition.GestureEventData) => void) {
2930
this._callback = callback;
@@ -35,6 +36,7 @@ export class GesturesObserver implements definition.GesturesObserver {
3536

3637
public observe(target: view.View, type: definition.GestureTypes, thisArg?: any) {
3738
if (target) {
39+
this.type = type;
3840
this._target = target;
3941
this._context = thisArg;
4042
this._onTargetLoaded = args => {
@@ -70,9 +72,6 @@ export class GesturesObserver implements definition.GesturesObserver {
7072

7173
private _dettach() {
7274
trace.write(this._target + "._detach() android:" + this._target.android, "gestures");
73-
if (this._target && this._target.android) {
74-
this._target.android.setOnTouchListener(null);
75-
}
7675

7776
this._onTouchListener = null;
7877
this._simpleGestureDetector = null;
@@ -86,7 +85,7 @@ export class GesturesObserver implements definition.GesturesObserver {
8685
this._dettach();
8786

8887
if (type & definition.GestureTypes.tap || type & definition.GestureTypes.doubleTap || type & definition.GestureTypes.longPress) {
89-
this._simpleGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new TapAndDoubleTapGestureListener(this, this._target));
88+
this._simpleGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new TapAndDoubleTapGestureListener(this, this._target, type));
9089
}
9190

9291
if (type & definition.GestureTypes.pinch) {
@@ -100,58 +99,6 @@ export class GesturesObserver implements definition.GesturesObserver {
10099
if (type & definition.GestureTypes.pan) {
101100
this._panGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new PanGestureListener(this, this._target));
102101
}
103-
104-
var that = new WeakRef(this);
105-
106-
this._onTouchListener = new android.view.View.OnTouchListener({
107-
onTouch: function (view: android.view.View, motionEvent: android.view.MotionEvent) {
108-
var owner = that.get();
109-
if (!owner) {
110-
return false;
111-
}
112-
113-
if (owner._simpleGestureDetector) {
114-
owner._simpleGestureDetector.onTouchEvent(motionEvent);
115-
}
116-
117-
if (owner._scaleGestureDetector) {
118-
owner._scaleGestureDetector.onTouchEvent(motionEvent);
119-
}
120-
121-
if (owner._swipeGestureDetector) {
122-
owner._swipeGestureDetector.onTouchEvent(motionEvent);
123-
}
124-
125-
if (owner._panGestureDetector) {
126-
owner._panGestureDetector.onTouchEvent(motionEvent);
127-
}
128-
129-
if (type & definition.GestureTypes.rotation && motionEvent.getPointerCount() === 2) {
130-
131-
var deltaX = motionEvent.getX(0) - motionEvent.getX(1);
132-
var deltaY = motionEvent.getY(0) - motionEvent.getY(1);
133-
var radians = Math.atan(deltaY / deltaX);
134-
var degrees = radians * (180 / Math.PI);
135-
136-
var args = <definition.RotationGestureEventData>{
137-
type: definition.GestureTypes.rotation,
138-
view: owner._target,
139-
android: motionEvent,
140-
rotation: degrees,
141-
}
142-
143-
var observer = that.get();
144-
if (observer && observer.callback) {
145-
observer.callback.call(observer._context, args);
146-
}
147-
148-
}
149-
150-
return true;
151-
}
152-
});
153-
154-
target.android.setOnTouchListener(this._onTouchListener);
155102
}
156103
}
157104

@@ -193,24 +140,30 @@ function _executeCallback(observer: GesturesObserver, args: definition.GestureEv
193140
class TapAndDoubleTapGestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
194141
private _observer: GesturesObserver;
195142
private _target: view.View;
143+
private _type: number;
196144

197-
constructor(observer: GesturesObserver, target: view.View) {
145+
constructor(observer: GesturesObserver, target: view.View, type: number) {
198146
super();
199147

200148
this._observer = observer;
201149
this._target = target;
150+
this._type = type;
202151
return global.__native(this);
203152
}
204153

205154
public onSingleTapConfirmed(motionEvent: android.view.MotionEvent): boolean {
206-
var args = _getArgs(definition.GestureTypes.tap, this._target, motionEvent);
207-
_executeCallback(this._observer, args);
155+
if (this._type === definition.GestureTypes.tap) {
156+
var args = _getArgs(definition.GestureTypes.tap, this._target, motionEvent);
157+
_executeCallback(this._observer, args);
158+
}
208159
return true;
209160
}
210161

211162
public onDoubleTap(motionEvent: android.view.MotionEvent): boolean {
212-
var args = _getArgs(definition.GestureTypes.doubleTap, this._target, motionEvent);
213-
_executeCallback(this._observer, args);
163+
if (this._type === definition.GestureTypes.doubleTap) {
164+
var args = _getArgs(definition.GestureTypes.doubleTap, this._target, motionEvent);
165+
_executeCallback(this._observer, args);
166+
}
214167
return true;
215168
}
216169

@@ -219,8 +172,10 @@ class TapAndDoubleTapGestureListener extends android.view.GestureDetector.Simple
219172
}
220173

221174
public onLongPress(motionEvent: android.view.MotionEvent): boolean {
222-
var args = _getArgs(definition.GestureTypes.longPress, this._target, motionEvent);
223-
_executeCallback(this._observer, args);
175+
if (this._type === definition.GestureTypes.longPress) {
176+
var args = _getArgs(definition.GestureTypes.longPress, this._target, motionEvent);
177+
_executeCallback(this._observer, args);
178+
}
224179
return true;
225180
}
226181
}

ui/gestures/gestures.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ declare module "ui/gestures" {
132132
* Disconnects the gesture observer.
133133
*/
134134
disconnect();
135+
136+
/**
137+
* Gesture type attached to the observer.
138+
*/
139+
type: GestureTypes;
135140
}
136141

137142
/**

ui/gestures/gestures.ios.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class UIGestureRecognizerImpl extends NSObject {
5858
export class GesturesObserver implements definition.GesturesObserver {
5959
public _callback: (args: definition.GestureEventData) => void;
6060
public _target: view.View;
61+
public type: definition.GestureTypes;
6162
private _recognizers: {};
6263
private _context: any;
6364

@@ -71,6 +72,7 @@ export class GesturesObserver implements definition.GesturesObserver {
7172

7273
public observe(target: view.View, type: definition.GestureTypes, thisArg?: any) {
7374
if (target) {
75+
this.type = type;
7476
this._target = target;
7577
this._context = thisArg;
7678
this._onTargetLoaded = args => {
@@ -89,7 +91,6 @@ export class GesturesObserver implements definition.GesturesObserver {
8991
this._attach(target, type);
9092
}
9193
}
92-
9394
}
9495

9596
private _attach(target: view.View, type: definition.GestureTypes) {

0 commit comments

Comments
 (0)