zoukankan      html  css  js  c++  java
  • 安卓webview下使用zepto的swipe失效

    安卓webview下使用zepto的swipe遇到的坑

      众所周知,安卓手机上touch事件一直有各种各样莫名其妙的问题。

      比如,我想要用swipeLeft/swipeRight监听向左向右滑动事件,如果只是单纯为元素增加swipeLeft/swipeRight事件的话在webview下是不生效的。google了下,还是有解决方法的。如果这个页面不需要上下滑动的话,完全可以用

    $('body').bind("touchmove", function(e) {     e.PReventDefault();});

    解决。即取消body的touchmove默认行为即可。(为什么取消body的touchmove默认行为就能让swipe生效呢?)  但这种做法太绝对太暴力了,如果页面需要上下滑动的话,那就会出问题。这里有两种情况,第一种是页面内的某个元素需要上下滑动,另一种是页面需要上下滑动。第一种情况,只是页面内某个元素需要上下滑动的话,可为这个元素监听touchmove事件,阻止冒泡。比如:

    $(id).bind("touchmove", function(e) {     e.stopPropagation()});

    这样这个元素就可以实现上下滑动了。  那如果是整个页面需要上下滑动呢?这就比较棘手了。  我一开始的方案是这样的。不监听swipe事件,全部用touch(touchStart/touchmove/touchEnd)实现,在touchStart事件里获取点击时的坐标位置(startX, startY),在touchEnd事件里获取手指离开时的坐标位置(endX,endY)。得到手指滑动的距离(distanceX,distanceY);  distanceX = startX - endX;  distanceY = startY - endY;  absoluteX = Math.abs(distanceX);//横向距离绝对值  absoluteY = Math.abs(distanceY);//纵向距离绝对值  比较absoluteX和absoluteY的大小,  absoluteY大则为上下滑动,不采取任何处理,  absoluteX大则为左右滑动,此时再比较startX - endX为正还是为负,正的话则则向左滑动,负的话为向右滑动。大概代码为这样

    var startX, startY;var endX, endY;var distanceX, distanceY;$('body').bind('touchstart', function(event) {    startX = event.targetTouches[0].clientX;    startY = event.targetTouches[0].clientY;}).bind('touchend', function(event) {    endX = event.changedTouches[0].clientX;    endY = event.changedTouches[0].clientY;    distanceX = Math.abs(startX - endX);    distanceY = Math.abs(startY - endY);    if (distanceX > distanceY) {        startX - endX > 0 ? swipeLeft() : swipeRight();    }});    

      本以为这样应该没什么问题了,结果···  在安卓webview下我模拟的swipe手势并不会触发touchend事件,我想这应该也是zepto自己封装的swipe事件失效的原因。  比如,我只点击了一下屏幕,其实就相当于执行了touchStart,紧接着执行了touchEnd。但如果我的手指在页面上进行了滑动操作,他就相当于执行了touchStart,紧接着执行了touchmove,然而手指离开时并不会执行touchEnd事件。那什么情况下它才会执行touchEnd事件呢?  答案是——把touchmove事件的默认行为取消的时候。(为什么执行了touchmove就不会执行touchend了呢?)  所以,还要对body的touchmove事件进行处理。思路是在用户刚开始滑动的时候,判断用户是想上下滑动还是左右滑动,上下滑动的话不做处理,左右滑动的话,对touchmove事件进行preventDefault()操作。如何判断用户刚开始滑动时是想左右还是想上下呢,可通过用户一开始滑动时X轴和Y轴方向的绝对距离进行判断。具体代码如下:

    var count = 0; //判断用户是否第一次进行touchmove操作var startX, startY;var endX, endY;var distanceX, distanceY;$('body').bind('touchstart', function(event) {    count = 0; //每次开始点击时清零    startX = event.targetTouches[0].clientX;    startY = event.targetTouches[0].clientY;}).bind('touchmove', function(event) {    if (count === 0) { //如果是第一次滑动        endX = event.changedTouches[0].clientX;        endY = event.changedTouches[0].clientY;        distanceX = Math.abs(startX - endX);        distanceY = Math.abs(startY - endY);        if (distanceX > distanceY) { //如果X绝对距离大于Y绝对距离            event.preventDefault();        }    }    count++; }).bind('touchend', function(event) {    endX = event.changedTouches[0].clientX;    endY = event.changedTouches[0].clientY;    distanceX = Math.abs(startX - endX);    distanceY = Math.abs(startY - endY);    if (distanceX > distanceY) {        startX - endX > 0 ? swipeLeft() : swipeRight();    }});

      问题完美解决。现在页面既可上下滑动也可左右滑动。补充: 之后google时无意间发现一篇文章(http://www.cnblogs.com/zldream1106/p/mobile_scroll_end.html)里面有说到swipe的问题IOS当"swipe"时,依次产生如下事件:touchstart -> touchmove * 多次 -> touchend -> scrollAndroid当"swipe"时,swipe虽然不会触发touchend事件,但是会在scroll事件之前触发一次touchcancel事件,即:touchstart -> touchmove ->touchcancel->scroll*多次Android端的话亲测确实如此,touchmove触发一次,touchcancel触发一次。IOS端的目前暂时还没自测过。所以,刚那个问题在安卓端的话方法二是可行的,只要把touchend改为touchcancel,但为了兼容起见,还是用方法三比较稳妥。但我还没明白为什么在安卓webview下swipe没有触发touchend事件,这个有待研究。

  • 相关阅读:
    hdu 4521 小明系列问题——小明序列(线段树 or DP)
    hdu 1115 Lifting the Stone
    hdu 5476 Explore Track of Point(2015上海网络赛)
    Codeforces 527C Glass Carving
    hdu 4414 Finding crosses
    LA 5135 Mining Your Own Business
    uva 11324 The Largest Clique
    hdu 4288 Coder
    PowerShell随笔3 ---别名
    PowerShell随笔2---初始命令
  • 原文地址:https://www.cnblogs.com/cangowu/p/5206528.html
Copyright © 2011-2022 走看看