滚动时的Phonegap移动应用程序选择不正确的项目

时间:2015-06-23 18:26:37

标签: javascript jquery ios cordova scroll

我有一个混合移动应用程序开发的手机差距,针对iOS设备。我使用Backbone.js作为我的MVC框架,jQuery,FastClick.js和Hammer.js用于事件。 我有一个可垂直滚动的项目列表。如果我点击某个项目,它应该打开详细信息视图。如果我在列表不滚动时点击该项目,这可以正常工作。但是如果我在列表滚动或减速时点击某个项目,它会选择错误的项目并显示其详细信息。 我在看 Tapping on scrolled list generates tap event for wrong elementjavascript scroll event for iPhone/iPad?以及其他建议我收听滚动列表onscroll事件的网站。只要用户滚动列表,就会触发此事件。我在onscroll的回调中禁用了tap事件。我在回调中设置一个定时器,超时为300ms,然后在该回调中启用tap事件,该事件在300 ms后执行。如果在计时器触发之前我得到另一个滚动事件,我取消之前的计时器并再次设置为300ms后触发。当滚动完全停止时,没有其他事件被触发。所以,我只能依靠这个事件。

问题是即使滚动减速但未完全停止,事件也会触发。因此,即使列表正在减速并且没有停止,计时器也会被触发,并且我再次遇到错误的详细信息选择问题。当滚动完全停止时,事件再次触发。 如果我将计时器增加到> 300毫秒,那么在非动量滚动的情况下,启用水龙头需要更长的时间,用户将继续多次点击。

以下是代码段:

加载视图时,请绑定tap事件和onscroll事件:

that.$('.scrollListItem').hammer().bind('tap',$.proxy(that.showDetail,that));
this.$('#scrollList').bind('scroll',$.proxy(this.checkscroll,this));

checkscroll功能

checkScroll: function(e){
  this.$('.scrollListItem').hammer().unbind('tap');
  clearTimeout(myGlobalScrollTimer);
  var that = this;
  myGlobalScrollTimer = setTimeout(function(){              
    that.$('.scrollListItem').hammer().bind('tap',$.proxy(that.showDetail,that));
  },300);
}

checkScroll功能即使在滚动列表正在减速且当前没有完全停止时也会触发。 如何检测到滚动完全停止且UI不再减速,然后才启用点击事件?有没有其他方法可以解决这个问题?请指教。

1 个答案:

答案 0 :(得分:6)

问题是由PhoneGap默认使用UIWebView而不是WKWebView(ios 8中引入)引起的。如果可以,请切换到使用新的WKWebView。我认为有一些插件,比如https://github.com/Telerik-Verified-Plugins/WKWebView,可以让你这样做。

WKWebView的一个好处是它具有明显更好的滚动事件保真度。实际上,您可能需要去抖动,因为在UIWebView仅发送1到3个滚动事件之前,您的应用将会收到数百个。

如果您感兴趣,滚动期间获得错误坐标的原因是UIWebView使用GPU滚动可滚动区域的位图,因此它不知道准确的坐标。

如果你必须在PhoneGap中使用UIWebView,请考虑使用“click”事件来避免许多讨厌的代码来确定是否实际发生了滚动。如果你真的需要快速点击,那么这里有几个技巧可以确定是否仍在进行滚动(这是从内存开始所以数字可能会稍微偏离)

  • 根据滚动的速度设置300ms超时变量。您可以根据最后touchmovetouchendtouchcancel的x或y的差异来确定速度(并使用事件的时间戳非常精确)。如果用户轻弹以产生高速,较长的滚动,则使用2.5秒的超时(根据需要调整)。如果是低速滚动,请使用300ms。如果用户只是拖动那么它的速度非常低,大约需要50ms。
  • 保留一个标记以跟踪您的代码是否认为它正在滚动。在touchstart上,清除该标志和触摸后的计时器将阻止ui滚动
  • scroll事件处理程序中,如果前一个滚动事件的时间戳超过1.25秒,则这可能是最后一次滚动事件,因此使用100ms的超时。如果这是touchend之后的第一个滚动事件,则使用上面的速度逻辑来确定超时。
  • touchend / touchcancel上,检查可滚动区域边缘的距离。如果它接近,则补偿,因为滚动一旦碰到边缘就会结束并产生弹性视觉效果。