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

后端 未结 2 705
灰色年华
灰色年华 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";
    });
    
    0 讨论(0)
  • 2021-02-03 15:21

    There is no need to use Javascript for this, it's overkill when the UIGestureRecognizerDelegate has adequate methods. All you need to do is make sure that when text selection is taking place, the tap recogniser isn't triggered.

    - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
        BOOL hasTap = ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] ||
                   [otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]);
        BOOL hasLongTouch = ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] ||
                         [otherGestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]);
        if (hasTap && hasLongTouch) {
            // user is selecting text
            return NO;
        }
        return YES;
    }
    

    That takes care of text selection, and links should work fine anyway (at least they do for me).

    0 讨论(0)
提交回复
热议问题