【问题标题】:Detect single tap in UIWebView, but still support text selection and links检测 UIWebView 中的单击,但仍支持文本选择和链接
【发布时间】:2012-01-19 20:01:04
【问题描述】:

我正在使用 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>

我正在拦截与我的 Web 视图代理的链接,并寻找“internal://tap”。当我得到它时,我会阻止 Web 视图导航,并响应点击。但是这样做我失去了选择文本的能力。点击链接仍然可以正常工作。

事实上,仅仅为“点击”添加一个事件监听器就会移除选择文本的能力,即使处理程序没有尝试更改文档位置。

知道我做错了什么吗?

【问题讨论】:

    标签: javascript iphone ios uiwebview


    【解决方案1】:

    没有必要为此使用 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;
    }
    

    这负责文本选择,并且链接无论如何都应该可以正常工作(至少它们对我有用)。

    【讨论】:

    • 谢谢!它对我有帮助!
    【解决方案2】:

    显然,如果你在一个元素上放置一个点击监听器,你就不能再在 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";
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-25
      相关资源
      最近更新 更多