衆所周知,安卓手機上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事件,這個有待研究。事件