iPad/iPhone双击问题

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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');
        
    );

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

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

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

【讨论】:

【参考方案2】:

我的建议是:

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

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

背景

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

    touchstart touchmove touchend 300 毫秒延迟,浏览器确保这是单击,而不是双击 mouseover mouseenter 注意:如果mouseovermouseentermousemove 事件更改了页面内容,则永远不会触发以下事件。 mousemove mousedown mouseup 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 因其他原因被触发并且没有触发点击事件(例如,用户滚动或缩放),并且随后尝试用鼠标跟踪链接(即在同时使用鼠标的设备上),这不起作用和触摸界面)。

进一步阅读

http://jsfiddle.net/macfreek/24Z5M/。在此沙盒中自行测试上述解决方案。 http://www.macfreek.nl/memory/Touch_and_mouse_with_hover_effects_in_a_web_browser。相同的答案,但有更多背景知识。 http://www.html5rocks.com/en/mobile/touchandmouse/。 html5rocks.com 上有关触摸和鼠标的一般背景文章。 https://developer.apple.com/library/ios/DOCUMENTATION/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html。 Safari Web 内容指南 - 处理事件。具体参见图 6.4,它解释了在 mouseovermousemove 事件期间内容更改后不会触发更多事件。

另见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 分钟。

以上是关于iPad/iPhone双击问题的主要内容,如果未能解决你的问题,请参考以下文章

C#中Listview的双击问题

双击,也触发了双击

单击事件和双击事件冲突问题

鼠标单击变双击怎么解决

javascript如何屏蔽鼠标双击,或将双击变成单击

鼠标双击怎么办,如何避免双击