mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 11:42:04 +08:00
Refactored gestures to support more scenarios in android.
This commit is contained in:
@ -1,5 +1,22 @@
|
|||||||
import frame = require("ui/frame");
|
import frame = require("ui/frame");
|
||||||
|
import pageModule = require("ui/page");
|
||||||
|
import textViewModule = require("ui/text-view");
|
||||||
|
|
||||||
export function buttonTap(args) {
|
export function buttonTap(args) {
|
||||||
frame.topmost().goBack();
|
console.log("tap");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function doubleTap(args) {
|
||||||
|
console.log("doubleTap");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function checkRecognizers(args) {
|
||||||
|
var testTextView = <textViewModule.TextView>(page.getViewById("testTextView"));
|
||||||
|
console.log("testTextView: " + testTextView.ios.gestureRecognizers);
|
||||||
|
}
|
||||||
|
|
||||||
|
var page: pageModule.Page;
|
||||||
|
|
||||||
|
export function pageLoaded(args) {
|
||||||
|
page = <pageModule.Page>args.object;
|
||||||
}
|
}
|
@ -1,3 +1,6 @@
|
|||||||
<Page xmlns="http://www.nativescript.org/tns.xsd">
|
<Page xmlns="http://www.nativescript.org/tns.xsd" loaded="pageLoaded">
|
||||||
<Button text="Back" tap="buttonTap"/>
|
<StackLayout>
|
||||||
|
<TextView text="TEST FOR GESTURES" id="testTextView" style="font-size: 50" tap="buttonTap" doubleTap="doubleTap"/>
|
||||||
|
<Button text="CLICK" tap="checkRecognizers" />
|
||||||
|
</StackLayout>
|
||||||
</Page>
|
</Page>
|
||||||
|
@ -18,6 +18,7 @@ import listViewModule = require("ui/list-view");
|
|||||||
import helper = require("../ui/helper");
|
import helper = require("../ui/helper");
|
||||||
import viewModule = require("ui/core/view");
|
import viewModule = require("ui/core/view");
|
||||||
import platform = require("platform");
|
import platform = require("platform");
|
||||||
|
import gesturesModule = require("ui/gestures");
|
||||||
|
|
||||||
export function test_load_IsDefined() {
|
export function test_load_IsDefined() {
|
||||||
TKUnit.assert(types.isFunction(builder.load), "ui/builder should have load method!");
|
TKUnit.assert(types.isFunction(builder.load), "ui/builder should have load method!");
|
||||||
@ -186,7 +187,7 @@ export function test_parse_ShouldParseBindingsToGestures() {
|
|||||||
p.bindingContext = context;
|
p.bindingContext = context;
|
||||||
var lbl = <labelModule.Label>p.content;
|
var lbl = <labelModule.Label>p.content;
|
||||||
|
|
||||||
var observer = (<any>lbl)._gesturesObserver;
|
var observer = (<any>lbl)._gestureObservers[gesturesModule.GestureTypes.tap][0];
|
||||||
|
|
||||||
TKUnit.assert(observer !== undefined, "Expected result: true.");
|
TKUnit.assert(observer !== undefined, "Expected result: true.");
|
||||||
TKUnit.assert(observer._context === context, "Context should be equal to binding context. Actual result: " + observer._context);
|
TKUnit.assert(observer._context === context, "Context should be equal to binding context. Actual result: " + observer._context);
|
||||||
|
@ -132,7 +132,7 @@ export class View extends proxy.ProxyObject implements definition.View {
|
|||||||
|
|
||||||
public _cssClasses: Array<string> = [];
|
public _cssClasses: Array<string> = [];
|
||||||
|
|
||||||
private _gesturesObserver: gestures.GesturesObserver;
|
public _gestureObservers = {};
|
||||||
private _updatingInheritedProperties: boolean;
|
private _updatingInheritedProperties: boolean;
|
||||||
|
|
||||||
public _options: definition.Options;
|
public _options: definition.Options;
|
||||||
@ -147,9 +147,22 @@ export class View extends proxy.ProxyObject implements definition.View {
|
|||||||
this._visualState = visualStateConstants.Normal;
|
this._visualState = visualStateConstants.Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(type: number, callback: (args: gestures.GestureEventData) => void, thisArg?: any): gestures.GesturesObserver {
|
observe(type: number, callback: (args: gestures.GestureEventData) => void, thisArg?: any): void {
|
||||||
this._gesturesObserver = gestures.observe(this, type, callback, thisArg);
|
var gesturesList = this._getGesturesList(type, true);
|
||||||
return this._gesturesObserver;
|
gesturesList.push(gestures.observe(this, type, callback, thisArg));
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getGesturesList(gestureType: number, createIfNeeded): Array<gestures.GesturesObserver> {
|
||||||
|
if (!gestureType) {
|
||||||
|
throw new Error("GestureType must be a valid gesture!");
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = this._gestureObservers[gestureType];
|
||||||
|
if (!list && createIfNeeded) {
|
||||||
|
list = [];
|
||||||
|
this._gestureObservers[gestureType] = list;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
getViewById<T extends View>(id: string): T {
|
getViewById<T extends View>(id: string): T {
|
||||||
|
@ -4,6 +4,7 @@ import trace = require("trace");
|
|||||||
import utils = require("utils/utils");
|
import utils = require("utils/utils");
|
||||||
import dependencyObservable = require("ui/core/dependency-observable");
|
import dependencyObservable = require("ui/core/dependency-observable");
|
||||||
import proxy = require("ui/core/proxy");
|
import proxy = require("ui/core/proxy");
|
||||||
|
import gestures = require("ui/gestures");
|
||||||
|
|
||||||
// merge the exports of the common file with the exports of this file
|
// merge the exports of the common file with the exports of this file
|
||||||
declare var exports;
|
declare var exports;
|
||||||
@ -77,6 +78,81 @@ export class View extends viewCommon.View {
|
|||||||
this._updateOnTouchListener(this.isUserInteractionEnabled);
|
this._updateOnTouchListener(this.isUserInteractionEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onLoaded() {
|
||||||
|
super.onLoaded();
|
||||||
|
this.setOnTouchListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
public onUnloaded() {
|
||||||
|
super.onUnloaded();
|
||||||
|
if (this.android && this.android.setOnTouchListener) {
|
||||||
|
this.android.setOnTouchListener(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setOnTouchListener() {
|
||||||
|
if (this.android && this.android.setOnTouchListener && Object.keys(this._gestureObservers).length > 0) {
|
||||||
|
var that = new WeakRef(this);
|
||||||
|
if (this.android.setClickable) {
|
||||||
|
this.android.setClickable(true);
|
||||||
|
}
|
||||||
|
this.android.setOnTouchListener(new android.view.View.OnTouchListener({
|
||||||
|
onTouch: function (view: android.view.View, motionEvent: android.view.MotionEvent) {
|
||||||
|
var owner = that.get();
|
||||||
|
if (!owner) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var i;
|
||||||
|
for (var prop in owner._gestureObservers) {
|
||||||
|
if (owner._gestureObservers.hasOwnProperty(prop)) {
|
||||||
|
for (i = 0; i < owner._gestureObservers[prop].length; i++) {
|
||||||
|
var gestureObserver = owner._gestureObservers[prop][i];
|
||||||
|
if (gestureObserver._simpleGestureDetector) {
|
||||||
|
gestureObserver._simpleGestureDetector.onTouchEvent(motionEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gestureObserver._scaleGestureDetector) {
|
||||||
|
gestureObserver._scaleGestureDetector.onTouchEvent(motionEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gestureObserver._swipeGestureDetector) {
|
||||||
|
gestureObserver._swipeGestureDetector.onTouchEvent(motionEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gestureObserver._panGestureDetector) {
|
||||||
|
gestureObserver._panGestureDetector.onTouchEvent(motionEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gestureObserver.type & gestures.GestureTypes.rotation && motionEvent.getPointerCount() === 2) {
|
||||||
|
|
||||||
|
var deltaX = motionEvent.getX(0) - motionEvent.getX(1);
|
||||||
|
var deltaY = motionEvent.getY(0) - motionEvent.getY(1);
|
||||||
|
var radians = Math.atan(deltaY / deltaX);
|
||||||
|
var degrees = radians * (180 / Math.PI);
|
||||||
|
|
||||||
|
var args = <gestures.RotationGestureEventData>{
|
||||||
|
type: gestures.GestureTypes.rotation,
|
||||||
|
view: owner,
|
||||||
|
android: motionEvent,
|
||||||
|
rotation: degrees,
|
||||||
|
ios: null
|
||||||
|
}
|
||||||
|
|
||||||
|
//var observer = that.get();
|
||||||
|
if (gestureObserver.callback) {
|
||||||
|
gestureObserver.callback.call(gestureObserver._context, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return owner.android.onTouchEvent(motionEvent);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public _addViewCore(view: viewCommon.View) {
|
public _addViewCore(view: viewCommon.View) {
|
||||||
if (this._context) {
|
if (this._context) {
|
||||||
view._onAttached(this._context);
|
view._onAttached(this._context);
|
||||||
|
2
ui/core/view.d.ts
vendored
2
ui/core/view.d.ts
vendored
@ -355,7 +355,7 @@ declare module "ui/core/view" {
|
|||||||
*/
|
*/
|
||||||
public focus(): boolean;
|
public focus(): boolean;
|
||||||
|
|
||||||
observe(type: number, callback: (args: gestures.GestureEventData) => void, thisArg?: any): gestures.GesturesObserver;
|
observe(type: number, callback: (args: gestures.GestureEventData) => void, thisArg?: any);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A basic method signature to hook an event listener (shortcut alias to the addEventListener method).
|
* A basic method signature to hook an event listener (shortcut alias to the addEventListener method).
|
||||||
|
@ -24,6 +24,7 @@ export class GesturesObserver implements definition.GesturesObserver {
|
|||||||
|
|
||||||
private _onTargetLoaded: (data: observable.EventData) => void;
|
private _onTargetLoaded: (data: observable.EventData) => void;
|
||||||
private _onTargetUnloaded: (data: observable.EventData) => void;
|
private _onTargetUnloaded: (data: observable.EventData) => void;
|
||||||
|
public type: definition.GestureTypes;
|
||||||
|
|
||||||
constructor(callback: (args: definition.GestureEventData) => void) {
|
constructor(callback: (args: definition.GestureEventData) => void) {
|
||||||
this._callback = callback;
|
this._callback = callback;
|
||||||
@ -35,6 +36,7 @@ export class GesturesObserver implements definition.GesturesObserver {
|
|||||||
|
|
||||||
public observe(target: view.View, type: definition.GestureTypes, thisArg?: any) {
|
public observe(target: view.View, type: definition.GestureTypes, thisArg?: any) {
|
||||||
if (target) {
|
if (target) {
|
||||||
|
this.type = type;
|
||||||
this._target = target;
|
this._target = target;
|
||||||
this._context = thisArg;
|
this._context = thisArg;
|
||||||
this._onTargetLoaded = args => {
|
this._onTargetLoaded = args => {
|
||||||
@ -70,9 +72,6 @@ export class GesturesObserver implements definition.GesturesObserver {
|
|||||||
|
|
||||||
private _dettach() {
|
private _dettach() {
|
||||||
trace.write(this._target + "._detach() android:" + this._target.android, "gestures");
|
trace.write(this._target + "._detach() android:" + this._target.android, "gestures");
|
||||||
if (this._target && this._target.android) {
|
|
||||||
this._target.android.setOnTouchListener(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._onTouchListener = null;
|
this._onTouchListener = null;
|
||||||
this._simpleGestureDetector = null;
|
this._simpleGestureDetector = null;
|
||||||
@ -86,7 +85,7 @@ export class GesturesObserver implements definition.GesturesObserver {
|
|||||||
this._dettach();
|
this._dettach();
|
||||||
|
|
||||||
if (type & definition.GestureTypes.tap || type & definition.GestureTypes.doubleTap || type & definition.GestureTypes.longPress) {
|
if (type & definition.GestureTypes.tap || type & definition.GestureTypes.doubleTap || type & definition.GestureTypes.longPress) {
|
||||||
this._simpleGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new TapAndDoubleTapGestureListener(this, this._target));
|
this._simpleGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new TapAndDoubleTapGestureListener(this, this._target, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type & definition.GestureTypes.pinch) {
|
if (type & definition.GestureTypes.pinch) {
|
||||||
@ -100,58 +99,6 @@ export class GesturesObserver implements definition.GesturesObserver {
|
|||||||
if (type & definition.GestureTypes.pan) {
|
if (type & definition.GestureTypes.pan) {
|
||||||
this._panGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new PanGestureListener(this, this._target));
|
this._panGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new PanGestureListener(this, this._target));
|
||||||
}
|
}
|
||||||
|
|
||||||
var that = new WeakRef(this);
|
|
||||||
|
|
||||||
this._onTouchListener = new android.view.View.OnTouchListener({
|
|
||||||
onTouch: function (view: android.view.View, motionEvent: android.view.MotionEvent) {
|
|
||||||
var owner = that.get();
|
|
||||||
if (!owner) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (owner._simpleGestureDetector) {
|
|
||||||
owner._simpleGestureDetector.onTouchEvent(motionEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (owner._scaleGestureDetector) {
|
|
||||||
owner._scaleGestureDetector.onTouchEvent(motionEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (owner._swipeGestureDetector) {
|
|
||||||
owner._swipeGestureDetector.onTouchEvent(motionEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (owner._panGestureDetector) {
|
|
||||||
owner._panGestureDetector.onTouchEvent(motionEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type & definition.GestureTypes.rotation && motionEvent.getPointerCount() === 2) {
|
|
||||||
|
|
||||||
var deltaX = motionEvent.getX(0) - motionEvent.getX(1);
|
|
||||||
var deltaY = motionEvent.getY(0) - motionEvent.getY(1);
|
|
||||||
var radians = Math.atan(deltaY / deltaX);
|
|
||||||
var degrees = radians * (180 / Math.PI);
|
|
||||||
|
|
||||||
var args = <definition.RotationGestureEventData>{
|
|
||||||
type: definition.GestureTypes.rotation,
|
|
||||||
view: owner._target,
|
|
||||||
android: motionEvent,
|
|
||||||
rotation: degrees,
|
|
||||||
}
|
|
||||||
|
|
||||||
var observer = that.get();
|
|
||||||
if (observer && observer.callback) {
|
|
||||||
observer.callback.call(observer._context, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
target.android.setOnTouchListener(this._onTouchListener);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,24 +140,30 @@ function _executeCallback(observer: GesturesObserver, args: definition.GestureEv
|
|||||||
class TapAndDoubleTapGestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
|
class TapAndDoubleTapGestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
|
||||||
private _observer: GesturesObserver;
|
private _observer: GesturesObserver;
|
||||||
private _target: view.View;
|
private _target: view.View;
|
||||||
|
private _type: number;
|
||||||
|
|
||||||
constructor(observer: GesturesObserver, target: view.View) {
|
constructor(observer: GesturesObserver, target: view.View, type: number) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this._observer = observer;
|
this._observer = observer;
|
||||||
this._target = target;
|
this._target = target;
|
||||||
|
this._type = type;
|
||||||
return global.__native(this);
|
return global.__native(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onSingleTapConfirmed(motionEvent: android.view.MotionEvent): boolean {
|
public onSingleTapConfirmed(motionEvent: android.view.MotionEvent): boolean {
|
||||||
var args = _getArgs(definition.GestureTypes.tap, this._target, motionEvent);
|
if (this._type === definition.GestureTypes.tap) {
|
||||||
_executeCallback(this._observer, args);
|
var args = _getArgs(definition.GestureTypes.tap, this._target, motionEvent);
|
||||||
|
_executeCallback(this._observer, args);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public onDoubleTap(motionEvent: android.view.MotionEvent): boolean {
|
public onDoubleTap(motionEvent: android.view.MotionEvent): boolean {
|
||||||
var args = _getArgs(definition.GestureTypes.doubleTap, this._target, motionEvent);
|
if (this._type === definition.GestureTypes.doubleTap) {
|
||||||
_executeCallback(this._observer, args);
|
var args = _getArgs(definition.GestureTypes.doubleTap, this._target, motionEvent);
|
||||||
|
_executeCallback(this._observer, args);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,8 +172,10 @@ class TapAndDoubleTapGestureListener extends android.view.GestureDetector.Simple
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onLongPress(motionEvent: android.view.MotionEvent): boolean {
|
public onLongPress(motionEvent: android.view.MotionEvent): boolean {
|
||||||
var args = _getArgs(definition.GestureTypes.longPress, this._target, motionEvent);
|
if (this._type === definition.GestureTypes.longPress) {
|
||||||
_executeCallback(this._observer, args);
|
var args = _getArgs(definition.GestureTypes.longPress, this._target, motionEvent);
|
||||||
|
_executeCallback(this._observer, args);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
ui/gestures/gestures.d.ts
vendored
5
ui/gestures/gestures.d.ts
vendored
@ -132,6 +132,11 @@ declare module "ui/gestures" {
|
|||||||
* Disconnects the gesture observer.
|
* Disconnects the gesture observer.
|
||||||
*/
|
*/
|
||||||
disconnect();
|
disconnect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gesture type attached to the observer.
|
||||||
|
*/
|
||||||
|
type: GestureTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,6 +58,7 @@ class UIGestureRecognizerImpl extends NSObject {
|
|||||||
export class GesturesObserver implements definition.GesturesObserver {
|
export class GesturesObserver implements definition.GesturesObserver {
|
||||||
public _callback: (args: definition.GestureEventData) => void;
|
public _callback: (args: definition.GestureEventData) => void;
|
||||||
public _target: view.View;
|
public _target: view.View;
|
||||||
|
public type: definition.GestureTypes;
|
||||||
private _recognizers: {};
|
private _recognizers: {};
|
||||||
private _context: any;
|
private _context: any;
|
||||||
|
|
||||||
@ -71,6 +72,7 @@ export class GesturesObserver implements definition.GesturesObserver {
|
|||||||
|
|
||||||
public observe(target: view.View, type: definition.GestureTypes, thisArg?: any) {
|
public observe(target: view.View, type: definition.GestureTypes, thisArg?: any) {
|
||||||
if (target) {
|
if (target) {
|
||||||
|
this.type = type;
|
||||||
this._target = target;
|
this._target = target;
|
||||||
this._context = thisArg;
|
this._context = thisArg;
|
||||||
this._onTargetLoaded = args => {
|
this._onTargetLoaded = args => {
|
||||||
@ -89,7 +91,6 @@ export class GesturesObserver implements definition.GesturesObserver {
|
|||||||
this._attach(target, type);
|
this._attach(target, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _attach(target: view.View, type: definition.GestureTypes) {
|
private _attach(target: view.View, type: definition.GestureTypes) {
|
||||||
|
Reference in New Issue
Block a user