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】:我的建议是:
在touchstart
和mouseenter
上添加悬停效果。
移除mouseleave
、touchmove
和click
上的悬停效果。
这类似于 Jake 的回答,但不需要模拟点击事件。
背景
为了模拟鼠标,如果用户在触摸屏(如 iPad)上触摸并释放手指,Webkit mobile 等浏览器会触发以下事件(来源:html5rocks.com 上的Touch And Mouse):
touchstart
touchmove
touchend
300 毫秒延迟,浏览器确保这是单击,而不是双击
mouseover
mouseenter
注意:如果mouseover
、mouseenter
或mousemove
事件更改了页面内容,则永远不会触发以下事件。
mousemove
mousedown
mouseup
click
似乎不可能简单地告诉网络浏览器跳过鼠标事件。
更糟糕的是,如果鼠标悬停事件更改了页面内容,则永远不会触发 click 事件,如 Safari Web Content Guide - Handling Events 中所述,尤其是 One-Finger Events 中的图 6.4。 “内容更改”究竟是什么,将取决于浏览器和版本。我发现对于 ios 7.0,背景颜色的更改不是(或不再是?)内容更改。
解决方案说明
回顾一下:
在touchstart
和mouseenter
上添加悬停效果。
移除mouseleave
、touchmove
和click
上的悬停效果。
请注意,touchend
上没有任何操作!
这显然适用于鼠标事件:mouseenter
和 mouseleave
(mouseover
和 mouseout
的略微改进版本)被触发,并添加和删除悬停。
如果用户实际上click
s 链接,悬停效果也会被移除。这确保如果用户在 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,它解释了在mouseover
或 mousemove
事件期间内容更改后不会触发更多事件。
另见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双击问题的主要内容,如果未能解决你的问题,请参考以下文章