在UIWebView中检测单击,但仍支持文本选择和链接

时间:2011-12-13 23:40:36

标签: javascript iphone ios uiwebview

我使用JavaScript来检测我在UIWebView中显示的页面中的点按,如下所示:

<div id="wrapper">
  <a href="http://apple.com">Apple</a>
</div>
<script>
  document.getElementById("wrapper").addEventListener('click', function() {
      document.location = 'internal://tap';
  }, false);
</script>

我拦截了与我的网络视图委托的链接,并寻找&#34; internal:// tap&#34;。当我得到它时,我阻止Web视图导航,并响应点击。但是这样做我失去了选择文本的能力。点击链接仍然可以正常工作。

事实上,只需添加一个事件监听器即可点击&#39;即使处理程序没有尝试更改文档位置,也会删除选择文本的功能。

知道我做错了吗?

2 个答案:

答案 0 :(得分:5)

显然,如果您在元素上放置一个单击侦听器,则无法再在iOS上的该元素中选择文本。我的解决方案是使用touchstart,touchmove和touchend事件的组合检测点击,以及忽略多次点击的计时器,并检查当前文档选择以确保选择事件不会继续。

这是我使用的JS代码:

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";
});

答案 1 :(得分:3)

没有必要使用Javascript,当UIGestureRecognizerDelegate有足够的方法时,它是过度的。您需要做的就是确保在进行文本选择时,不会触发点击识别器。

- (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;
}

负责文本选择,无论如何链接都应该正常工作(至少它们适用于我)。