在列表视图中,我发生了两个事件,一个轻击事件和一个longpress事件,但longpress同时触发。 在.html文件中:
fs::write("/proc/acpi/bbswitch", data)
.map_err(|e| BbswitchError::BbswitchNotAvailable { cause: e }.into())
然后是.ts文件
<ListView class="listViewContainer" [items]="contactList">
<ng-template let-item="item" let-i="index">
<StackLayout
(loaded)="loaded($event)"
orientation="horizontal"
class="preview-info-container"
>
</StackLayout>
</ng-template>
</ListView>
我的问题是,长按特定字段时如何防止触发轻击事件?
这可能是NativeScript tap & longPress together not working的重复问题,但是由于没有明确的答案,我想再次提出。
修改 更多信息: 项目tns版本是
loaded(args) {
const element = args.object;
element.on("loaded, tap, longPress", (args) => {
// console.log("Event: " + args.eventName + ", sender: " + args.object);
if(args.eventName === "tap") {
this.router.navigate(["card/contact/" + this.contact.id]);
} else {
this.togglePreviewOptions = !this.togglePreviewOptions;
}
});
}
全球本地脚本版本
$ tns --version 4.3.0-2018-08-31-12160
仿真器版本:
nativescript@4.3.0-2018-08-31-12160
答案 0 :(得分:2)
我们还遇到了两个事件都在iOS上触发的问题。 基于@GeorgeK的答案,我将他的方法包装在服务中。 我还确保您可以使用项目标识符同时按下多个项目。我还为cancel和move动作添加了一个处理程序,以防止在滚动时选择项目:
touch-event.service.ts:
import { Injectable } from "@angular/core";
import { TouchGestureEventData } from "tns-core-modules/ui/gestures";
@Injectable({
providedIn: "root"
})
export class TouchEventService {
static longPressTimeout: number = 500;
private events: Map<string, number> = new Map<string, number>();
private startY: Map<string, number> = new Map<string, number>();
private startX: Map<string, number> = new Map<string, number>();
constructor() {
}
onTouch(args: TouchGestureEventData, id: string, item: any, itemTapCallback?: (item: any) => any, longPressCallback?: (item: any) => any) {
if (args.action === "down") {
// When someone starts pressing the element.
// Create a new timeout that will trigger the long press callback
// after longPressTimeout.
this.startX.set(id, args.getX());
this.startY.set(id, args.getY());
// @ts-ignore
this.events.set(id, setTimeout(() => {
this.clearItem(id);
longPressCallback(item);
}, TouchEventService.longPressTimeout));
} else if (args.action === "up" && this.events.has(id)) {
// When someone stops pressing the element.
// If we have an existing event, this means the long press did
// not trigger yet. Remove the timeout and trigger the tap callback.
clearTimeout(this.events.get(id));
this.clearItem(id);
itemTapCallback(item);
} else if (args.action === "cancel" && this.events.has(id)) {
// When someone moves away from the element while pressing.
// Prevents handlers to be called while scrolling.
clearTimeout(this.events.get(id));
this.clearItem(id);
} else if (args.action === "move" && this.events.has(id)) {
// When someone moves from the element while pressing.
// Prevents handlers to be called while scrolling.
// This is mainly for iOS because they do not trigger cancel
// when scrolling out of view. But also useful for large items.
const differenceX = Math.abs(args.getX() - this.startX.get(id));
const differenceY = Math.abs(args.getY() - this.startY.get(id));
if (differenceX > 30 || differenceY > 10) {
clearTimeout(this.events.get(id));
this.clearItem(id);
}
}
}
clearItem(id: string) {
this.events.delete(id);
this.startX.delete(id);
this.startY.delete(id);
}
}
这是一个如何在组件中实现它的示例: example.component.ts
import { Component } from "@angular/core";
import { TouchEventService } from "./touch-event.service";
@Component({
selector: "Example",
templateUrl: "./example.component.html"
})
export class ExampleComponent {
private _itemTapHandler: (item: any) => any;
private _longPressHandler: (item: any) => any;
constructor(public touchEventService: TouchEventService) {
this._itemTapHandler = this.itemTapHandler();
this._longPressHandler = this.longPressHandler();
}
itemTapHandler(): (item: any) => any {
return (item) => {
return this.itemTap(item);
};
}
longPressHandler(): (item: any) => any {
return (item) => {
return this.longPress(item);
};
}
itemTap(item: any) {
// Handle the item tap here.
}
longPress(item: any) {
// Handle the long press here.
}
}
example.component.html
<StackLayout *ngFor="let item of items" (touch)="touchEventService.onTouch($event, item.id, item, _itemTapHandler, _longPressHandler)">
<!-- Your item content here, you can use the touch in anything, like list views and scroll views -->
</StackLayout>
答案 1 :(得分:1)
在模板代码中定义2个事件将更加容易:
<ListView class="listViewContainer" [items]="contactList">
<ng-template let-item="item" let-i="index">
<StackLayout
(loaded)="loaded($event)"
(tap)="functionWhenTap(item)"
(longPress)="functionWhenLongPress(item)"
orientation="horizontal"
class="preview-info-container"
>
</StackLayout>
</ng-template>
</ListView>
,然后使用以下命令在您的.ts
文件中进行处理:
functionWhenTap(item: any) {
// your things to do when tapped
}
functionWhenLongPress(item: any) {
// your things to do when long pressed
}
这是一段实际的代码。也应该为您工作。
这是在我的个人个人设备上测试过的工作示例: https://play.nativescript.org/?template=play-ng&id=XgBfFE
答案 2 :(得分:0)
我无法通过添加两个不同的事件(tap / longPress)来解决此问题。 作为解决方案,我使用以下
在.html
内
<StackLayout (touch)="onTouch($event)">
<Contact-Preview [contact]=contactList[i]></Contact-Preview>
</StackLayout>
在.ts
内
onTouch(args: TouchGestureEventData) {
if(args.action === "down") {
this.start = new Date().getMilliseconds();
}
if(args.action === "up") {
this.end = new Date().getMilliseconds();
const duration = Math.abs(this.start - this.end)
console.log(duration > 150? "long press": "tap")
}
}
这可以防止同时触发tap和longPress事件,从而解决我的问题。
答案 3 :(得分:0)
更明确的是使用指令:
import { Directive, HostListener, Output, EventEmitter } from "@angular/core";
import { TouchAction, TouchGestureEventData } from "@nativescript/core";
@Directive({
selector: "[press], [pressHold]",
})
export class PressDirective {
@Output() press: EventEmitter<void> = new EventEmitter();
@Output() pressHold: EventEmitter<void> = new EventEmitter();
private readonly pressHoldTimeout: number = 500;
private _startPress: number;
private _timeout: NodeJS.Timeout;
private _cancel: boolean;
@HostListener("touch", ["$event"])
touch(event: TouchGestureEventData) {
switch (event.action) {
case TouchAction.down:
this._cancel = false;
this._startPress = Date.now();
this._timeout = setTimeout(() => {
this.pressHold.emit();
}, this.pressHoldTimeout);
break;
case TouchAction.up:
if (
!this._cancel &&
Date.now() - this._startPress < this.pressHoldTimeout
) {
clearTimeout(this._timeout);
this.press.emit();
}
break;
case TouchAction.move:
case TouchAction.cancel:
clearTimeout(this._timeout);
this._cancel = true;
break;
}
}
}
在模板中:enter code here
<Button
(press)="onPress()"
(pressHold)="onPressHold()"
text="press && hold"
>
</Button>