Platform: iOS
TNS: 2.5.0
When using the longPress gesture, it will fire once (as it should) and then when you let go of your finger, it fires again. This isn't intentional, is it?
There's no state
or action
property of the event, so there's no such thing as an "up" event to handle.
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
Hi @NordlingArt,
Thank you for reporting this issue.
I was able to reproduce this behavior on my side and confirm that this is a real issue for iOS. I am also attaching sample code, where the problem could be reproduced.
main-page.xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
<Page.actionBar>
<ActionBar title="My App" icon="" class="action-bar">
</ActionBar>
</Page.actionBar>
<StackLayout class="p-20">
<Label loaded="labelLoaded" text="Tap the button" class="h1 text-center" />
<Button text="TAP" tap="{{ onTap }}" class="btn btn-primary btn-active"/>
<Label text="{{ message }}" class="h2 text-center" textWrap="true"/>
</StackLayout>
</Page>
main-page.ts
import { EventData } from 'data/observable';
import { Page } from 'ui/page';
import { HelloWorldModel } from './main-view-model';
import { GestureTypes, GestureEventData, TouchGestureEventData } from "ui/gestures";
import labelModule = require("ui/label");
import {isIOS} from "platform"
// Event handler for Page "navigatingTo" event attached in main-page.xml
var viewmodel = new HelloWorldModel()
var statedown=true
export function navigatingTo(args: EventData) {
let page = <Page>args.object;
page.bindingContext = viewmodel;
}
export function labelLoaded(args){
var label = args.object;
label.on("longPress", function (args: GestureEventData) {
console.log("longPress");
console.log(args.eventName);
console.log(args.type);
});
}
As a workaround, you could create one custom flag, which will allow you to determine the second fire of the event on iOS.
main-page.ts
import { EventData } from 'data/observable';
import { Page } from 'ui/page';
import { HelloWorldModel } from './main-view-model';
import { GestureTypes, GestureEventData, TouchGestureEventData } from "ui/gestures";
import labelModule = require("ui/label");
import {isIOS} from "platform"
// Event handler for Page "navigatingTo" event attached in main-page.xml
var viewmodel = new HelloWorldModel()
var statedown=true
export function navigatingTo(args: EventData) {
let page = <Page>args.object;
page.bindingContext = viewmodel;
}
export function labelLoaded(args){
var label = args.object;
label.on("longPress", function (args: GestureEventData) {
console.log(statedown)
if(isIOS){
if(statedown){
console.log("longPress");
console.log(args.eventName);
console.log(args.type);
statedown=false;
}
else{
statedown=true;
}
}
});
}
longPress
gesture does not have state
or action
property. For this case, you could use touch
gesture, where you could handle the state while using its action
property.
label.on(GestureTypes.touch, function (args: TouchGestureEventData) {
console.log("Touch: x: " + args.getX() + " y: " + args.getY());
console.log(args.action)
});
@tsonevn - Thanks for confirming issue. I have applied a custom flag as a temporary work around.
Please note the event actually fires multiple times; try holding the mouse down and then moving while doing a long press....
Confirmed, just ran into this.
Having the same, any updates?
Hi @terreb,
This is still a valid issue for iOS. Regarding that, this problem is still under review and I could not commit to the exact time, where it would be fixed. You could keep track on the issue for further info and in the meantime, you could use the above-given workaround.
@tsonevn, ok thank you.
TNS 3.2.1, iOS
Having the same, any updates?
Base on the iOS documentation, we could check the state of the gesture and to allow executing our functionality only on long press ended.
In the meantime, we could workaround this case as follow:
<Label textWrap="true" text="Play with NativeScript!"v backgroundColor="green" height="200"
class="h2 description-label" loaded="labelLoaded"/>
import { GestureTypes, GestureEventData } from "tns-core-modules/ui/gestures";
abelLoaded(args) {
console.log("add gesture- label: " + NgZone.isInAngularZone());
let label: Label = <Label>args.object;
label.on(GestureTypes.longPress, (args: GestureEventData) => {
if (args.ios.state !== 3)
return;
console.log("long press");
});
}
reproducible with modules 4.1
This is not a bug but a feature of iOS I guess. We should just check the state on iOS. Should this issue still be opened?
Can you explain why triggering a method can be a feature?
They implemented states into event. You can track when it starts, continues and ends. That means it is clearly something intended. Not a bug. Maybe you can use this to drag something around. It would be handy if you could track that.
// Assume platform is iOS
exports.onLongPress = args => {
switch(args.ios.state) {
case UIGestureRecognizerStateBegan: // 1
// The long press event has begun.
break;
case UIGestureRecognizerStateChanged: // 2
// The long press event has changed.
break;
case UIGestureRecognizerStateEnded: // 3
// The long press event has ended.
break;
}
}
A good thing would be to return the state directly in the gesture event and in the ios object. It is the case for some gesture events but not all.
Hey @NickIliev...
Just ran in to this issue myself ({N}6.3), and while the solution provided above (manually checking the UIGestureRecognizer's state) works, I wondered if this will be fixed in upcoming releases of NS...
These are the sorts of things that (I feel) are holding NativeScript back––weird, inconsistent behaviour across versions, platforms, etc. (though they are also the hardest to perfect, of course)
Thanks for your help, @tsonevn and @NickIliev!
@farfromrefug @fgutteridge I've opened this PR which is proving the state as an argument for longPress event on iOS (via GestureEventDataWithState
interface).
Example:
export function testLongPress(args: GestureEventDataWithState) {
console.log(`LongPress fired!`);
console.log(`>>> args.state ${args.state}`);
}
Note: As Android doesn't support states I've made it so it would always return state 1 when the long press is triggered on Android
Looks great, @NickIliev! Thanks so much for your help. Yes, having the longPress
event exposed statefully (for iOS at least) makes the most sense.
Most helpful comment
@farfromrefug @fgutteridge I've opened this PR which is proving the state as an argument for longPress event on iOS (via
GestureEventDataWithState
interface).Example:
Note: As Android doesn't support states I've made it so it would always return state 1 when the long press is triggered on Android