Detect single tap in UIWebView, but still support text selection and links

后端 未结 2 706
灰色年华
灰色年华 2021-02-03 14:41

I\'m using JavaScript to detect taps in a page I\'m showing in a UIWebView, like so:


      
2条回答
  •  梦如初夏
    2021-02-03 15:06

    Apparently if you put a click listener on an element, you can no longer select text within that element on iOS. My solution was to detect taps using a combination of touchstart, touchmove, and touchend events, along with a timer to ignore multi-taps, and checking the current document selection to make sure a selection event is not going on.

    Here's the JS code I used:

    SingleTapDetector = function(element, handler) {
        this.element = element;
        this.handler = handler;
    
        element.addEventListener('touchstart', this, false);
    };
    
    SingleTapDetector.prototype.handleEvent = function(event) {
        switch (event.type) {
            case 'touchstart': this.onTouchStart(event); break;
            case 'touchmove': this.onTouchMove(event); break;
            case 'touchend': this.onTouchEnd(event); break;
        }
    };
    
    SingleTapDetector.prototype.onTouchStart = function(event) {
        this.element.addEventListener('touchend', this, false);
        document.body.addEventListener('touchmove', this, false);
    
        this.startX = this.currentX = event.touches[0].clientX;
        this.startY = this.currentY = event.touches[0].clientY;
        this.startTime = new Date().getTime();
    };
    
    SingleTapDetector.prototype.onTouchMove = function(event) {
        this.currentX = event.touches[0].clientX;
        this.currentY = event.touches[0].clientY;
    };
    
    SingleTapDetector.prototype.onTouchEnd = function(event) {
        var that = this;
    
        // Has there been one or more taps in this sequence already?
        if (this.tapTimer) {
            // Reset the timer to catch any additional taps in this sequence
            clearTimeout(this.tapTimer);
            this.tapTimer = setTimeout(function() {
                that.tapTimer = null;
            }, 300);
        } else {
            // Make sure the user didn't move too much
            if (Math.abs(this.currentX - this.startX) < 4 &&
                Math.abs(this.currentY - this.startY) < 4) {
                // Make sure this isn't a long press
                if (new Date().getTime() - this.startTime <= 300) {
                    // Make sure this tap wasn't part of a selection event
                    if (window.getSelection() + '' == '') {                    
                        // Make sure this tap is in fact a single tap
                        this.tapTimer = setTimeout(function() {
                            that.tapTimer = null;
    
                            // This is a single tap
                            that.handler(event);
                        }, 300);
                    }
                }
            }
        }
    };
    
    new SingleTapDetector(document.body, function(event) {
        document.location = "internal://tap";
    });
    

提交回复
热议问题