Ionic 5 - long press gesture example

I improved the directive to include a tap (opposite of a long press). It also checks if the user dragged their finger, cancelling the “press” (because it’s a “drag” now).

Here is the directive and example:

import {
    Directive,
    ElementRef,
    Input,
    AfterViewInit,
    NgZone,
    EventEmitter,
    Output
} from "@angular/core";
import { GestureController } from "@ionic/angular";

@Directive({
    selector: "[long-press]"
})
export class LongPressDirective implements AfterViewInit {

    @Output() tap = new EventEmitter();
    @Output() press = new EventEmitter();
    @Input("delay") delay = 300;
    action: any; //not stacking actions

    private positions = {
        start: {
            x: undefined as number,
            y: undefined as number
        },
        current: {
            x: undefined as number,
            y: undefined as number,
        }
    }

    private longPressActive = false;

    constructor(
        private el: ElementRef,
        private gestureCtrl: GestureController,
        private zone: NgZone
    ) { }

    ngAfterViewInit() {
        this.loadLongPressOnElement();
    }

    loadLongPressOnElement() {
        const gesture = this.gestureCtrl.create({
            el: this.el.nativeElement,
            threshold: 0,
            gestureName: 'long-press',
            onStart: ev => {
                this.longPressActive = true;
                this.longPressAction();

                this.positions = {
                    start: { x: ev.startX, y: ev.startY },
                    current: { x: ev.currentX, y: ev.currentY }
                };

            },
            onMove: ev => {
                this.positions.current = { x: ev.currentX, y: ev.currentY };
            },
            onEnd: ev => {
                this.longPressActive = false;
            }
        });
        gesture.enable(true);
    }

    private longPressAction() {
        if (this.action) {
            clearInterval(this.action);
        }
        this.action = setTimeout(() => {
            this.zone.run(() => {
                // Check distance
                const xDistance = Math.abs(this.positions.start.x - this.positions.current.x);
                const yDistance = Math.abs(this.positions.start.y - this.positions.current.y);
                if(xDistance > 15 || yDistance > 15)
                    // User dragged finger
                    return;

                if (this.longPressActive === true) {
                    this.longPressActive = false;
                    this.press.emit();
                } else {
                    this.tap.emit();
                }
            });
        }, this.delay);
    }
}
<ion-button long-press (press)="onLongPress()" (tap)="onTap()"></ion-button>

My iteration was built on your shoulders marcelomoraesaguiar. Thank you for posting.

1 Like