【问题标题】:iPad/iPhone double click problemiPad/iPhone双击问题
【发布时间】:2011-11-26 06:02:30
【问题描述】:

我遇到了与iPad/iPhone hover problem causes the user to double click a link 非常相似的问题,用户点击链接必须点击两次才能真正访问它。

我在那个问题中实现了解决方案,但我现在遇到了一个新问题。重定向发生在用户点击链接时,但无论如何都会发生。因此,即使用户试图滚动页面,并且他们在链接上开始滚动,当他们松开滚动时,页面也会重定向。

有没有办法保留链接,以便它们只需点击一下,但如果它们正在滚动,不要重定向页面?

【问题讨论】:

    标签: jquery iphone html ipad mobile


    【解决方案1】:

    这是我最终做的:

    问题是 touchstart 和 touchend 只知道触摸事件,不知道滚动事件,所以它们只对开始触摸和结束触摸做出反应。我们要做的是区分滚动和不滚动。这是我所做的:

    $('a')
        .live('touchstart', function(){
            isScrolling = false;
        })
        .live('touchmove', function(e){
            isScrolling = true;
        })
        .live('touchend', function(e){
            if( !isScrolling )
            {
                window.location = $(this).attr('href');
            }
        });
    

    这会按顺序执行这些操作:

    1. 首次记录触摸时,将 isScrolling 设置为 false。
    2. 当触摸移动时,将 isScrolling 设置为 true。如果触摸不移动,则不会发生这种情况。
    3. 当触摸停止时,如果没有发生滚动,则将页面重定向到链接的 href。

    编辑:过了一会儿,我发现问题是由 SuperFish 引起的。当页面小于一定宽度时禁用 superfish 解决了这个问题。

    【讨论】:

      【解决方案2】:

      我的建议是:

      • touchstartmouseenter 上添加悬停效果。
      • 移除mouseleavetouchmoveclick 上的悬停效果。

      这类似于 Jake 的回答,但不需要模拟点击事件。

      背景

      为了模拟鼠标,如果用户在触摸屏(如 iPad)上触摸并释放手指,Webkit mobile 等浏览器会触发以下事件(来源:html5rocks.com 上的Touch And Mouse):

      1. touchstart
      2. touchmove
      3. touchend
      4. 300 毫秒延迟,浏览器确保这是单击,而不是双击
      5. mouseover
      6. mouseenter
        • 注意:如果mouseovermouseentermousemove 事件更改了页面内容,则永远不会触发以下事件。
      7. mousemove
      8. mousedown
      9. mouseup
      10. click

      似乎不可能简单地告诉网络浏览器跳过鼠标事件。

      更糟糕的是,如果鼠标悬停事件更改了页面内容,则永远不会触发 click 事件,如 Safari Web Content Guide - Handling Events 中所述,尤其是 One-Finger Events 中的图 6.4。 “内容更改”究竟是什么,将取决于浏览器和版本。我发现对于 iOS 7.0,背景颜色的更改不是(或不再是?)内容更改。

      解决方案说明

      回顾一下:

      • touchstartmouseenter 上添加悬停效果。
      • 移除mouseleavetouchmoveclick 上的悬停效果。

      请注意,touchend 上没有任何操作!

      这显然适用于鼠标事件:mouseentermouseleavemouseovermouseout 的略微改进版本)被触发,并添加和删除悬停。

      如果用户实际上clicks 链接,悬停效果也会被移除。这确保如果用户在 Web 浏览器中按下后退按钮,它会被删除。

      这也适用于触摸事件:在touchstart 上添加了悬停效果。它在touchend 上被“删除”。它在mouseenter 上再次添加,并且由于这不会导致内容更改(它已经添加),因此click 事件也会被触发,并且无需用户再次点击链接!

      浏览器在touchstart 事件和click 之间的 300 毫秒延迟实际上得到了很好的利用,因为悬停效果会在这很短的时间内显示出来。

      如果用户决定取消点击,手指的移动将照常执行。通常,这是一个问题,因为没有触发 mouseleave 事件,并且悬停效果仍然存在。值得庆幸的是,可以通过移除 touchmove 上的悬停效果轻松解决此问题。

      就是这样!

      请注意,可以删除 300 毫秒的延迟,例如使用 FastClick library,但这超出了本问题的范围。

      替代解决方案

      我发现以下替代方案存在以下问题:

      • 浏览器检测:极易出错。假设设备具有鼠标或触控功能,而当触控显示器激增时,两者的结合将变得越来越普遍。
      • CSS 媒体检测: 我所知道的唯一纯 CSS 解决方案。仍然容易出错,并且仍然假定设备具有鼠标或触摸功能,而两者都是可能的。
      • 模拟touchend 中的点击事件:这将错误地跟随链接,即使用户只想滚动或缩放,而没有实际点击链接的意图。
      • 使用变量来抑制鼠标事件: 这会在touchend 中设置一个变量,该变量用作后续鼠标事件中的 if 条件,以防止在该时间点发生状态更改。变量在点击事件中被重置。如果您真的不希望在触摸界面上产生悬停效果,这是一个不错的解决方案。不幸的是,如果touchend 因其他原因被触发并且没有触发点击事件(例如,用户滚动或缩放),并且随后尝试用鼠标跟踪链接(即在同时使用鼠标的设备上),这不起作用和触摸界面)。

      进一步阅读

      另见Disable hover effects on mobile browsers

      【讨论】:

        【解决方案3】:

        如果您的内容在UIScrollView 中,您可以(或可能已经)实现UIScrollViewDelegate;其中包含以下方法:

        -(void)scrollViewDidScroll: (UIScrollView*)scrollView
        

        如果你使用这个,得到以下:

        float offset = scrollView.contentOffset.y;
        
        if (offset > 0)
            // then we have started to scroll
        

        如果您将此条件与检测屏幕上当前的点击/按下次数(即,在您的情况下只有一次)结合使用,则忽略链接时可能发生的任何触发调用(如果 >1 次点击)轻拍。

        希望这会有所帮助!

        【讨论】:

        • 我想出了一个让它工作的方法。我打算将其发布为答案,但 SO 不会让我在 8 小时内这样做。还有 55 分钟。
        猜你喜欢
        • 2011-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-01
        • 2011-04-24
        相关资源
        最近更新 更多