安卓webview下使用zepto的swipe失效

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

  衆所周知,安卓手機上touch事件一直有各類各樣莫名其妙的問題。html

  好比,我想要用swipeLeft/swipeRight監聽向左向右滑動事件,若是隻是單純爲元素增長swipeLeft/swipeRight事件的話在webview下是不生效的。google了下,仍是有解決方法的。若是這個頁面不須要上下滑動的話,徹底能夠用web

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

解決。即取消body的touchmove默認行爲便可。(爲何取消body的touchmove默認行爲就能讓swipe生效呢?)  但這種作法太絕對太暴力了,若是頁面須要上下滑動的話,那就會出問題。這裏有兩種狀況,第一種是頁面內的某個元素須要上下滑動,另外一種是頁面須要上下滑動。第一種狀況,只是頁面內某個元素須要上下滑動的話,可爲這個元素監聽touchmove事件,阻止冒泡。好比:google

$(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爲正仍是爲負,正的話則則向左滑動,負的話爲向右滑動。大概代碼爲這樣htm

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軸方向的絕對距離進行判斷。具體代碼以下:blog

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事件,這個有待研究。事件

相關文章
相關標籤/搜索