【问题标题】:Phonegap mobile app tapping while scrolling selects incorrect item滚动时点击Phonegap移动应用程序选择不正确的项目
【发布时间】:2015-09-09 17:12:49
【问题描述】:

我有一个混合移动应用程序,该应用程序通过电话差距开发并针对仅 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 的回调中禁用了点击事件。我在回调中设置了一个计时器,超时时间为 300 毫秒,然后在该回调中启用点击事件,该事件在 300 毫秒后执行。如果我在计时器触发之前收到另一个滚动事件,我会取消之前的计时器并再次将其设置为在 300 毫秒后触发。当滚动完全停止时,不会触发其他事件。所以,我只能依靠这个事件。

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

下面是sn-ps的代码:

当视图加载时,绑定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 不再减速,然后才启用点击事件?有没有其他方法可以解决这个问题?请指教。

【问题讨论】:

  • 投反对票的人至少可以评论为什么投反对票吗?

标签: javascript jquery ios cordova scroll


【解决方案1】:

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

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

如果您有兴趣,您在滚动过程中得到不正确坐标的原因是 UIWebView 使用 GPU 滚动您的可滚动区域的位图,因此它不知道准确的坐标。

如果您必须在 PhoneGap 中使用 UIWebView,请考虑使用“点击”事件来避免使用大量讨厌的代码来确定是否真的发生了滚动。如果你真的需要快速点击,那么这里有几个技巧可以确定滚动是否仍在发生(这是从内存中获取的,所以数字可能有点偏)

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

【讨论】:

  • 感谢您的详细解释。我已经尝试了其中一些选项(例如速度计算并相应地调整时间),但我会考虑尝试你提到的其他方法,因为单独的速度不会产生预期的结果。我也在考虑只使用 iScroll 以便准确获取 scrollend 事件。
猜你喜欢
  • 2012-01-21
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多