2010-06-07 100 views
32

我剛開始考慮在android上做一些基本的移動web開發,並編寫測試腳本來調查觸摸事件。我在android模擬器中運行了以下代碼,並且touchend事件永遠不會被觸發。誰能告訴我爲什麼?touchend事件不適用於Android

我已經嘗試過三個版本的模擬器(1.6,2.1和2.2),並且所有三個版本的行爲都是一樣的。

在此先感謝您提供的任何幫助。

乾杯, 科爾姆

編輯 - 我也試過這種使用XUI框架,並有同樣的問題,所以我猜我有這個東西是如何工作的一個根本性的誤解......

地圖測試

<meta name="description" content="" /> 
    <meta name="keywords" content="" /> 
    <meta name="language" content="english" /> 

    <meta name="viewport" content="minimum-scale=1.0, 
            width=device-width, 
            height=device-height, 
            user-scalable=no"> 
    <script type="text/javascript"> 
     window.onload = function(){ 
      document.body.appendChild(
        document.createTextNode("w: " + screen.width + " x " + "h : " +screen.height) 
      ); 
      attachTouchEvents(); 
     } 
     function attachTouchEvents() { 
      console = document.getElementById("console"); 
      var map = document.getElementById("map"); 
      map.addEventListener ('touchstart', function (event) { 
       event.preventDefault(); 
       var touch = event.touches[0]; 
       document.getElementById("touchCoord").innerHTML = "S : " + touch.pageX + " " + touch.pageY; 
       document.getElementById("touchEvent").innerHTML = "Touch Start"; 
      }, false); 

      map.addEventListener ('touchmove', function (event) { 
       event.preventDefault(); 
       var touch = event.touches[0]; 
       document.getElementById("touchCoord").innerHTML = "M : " + touch.pageX + " " + touch.pageY; 
       document.getElementById("touchEvent").innerHTML = "Touch Move"; 
      }, false); 

      map.addEventListener ('touchend', function (event) { 
       var touch = event.touches[0]; 
       document.getElementById("touchCoord").innerHTML = "E : " + touch.pageX + " " + touch.pageY; 
       document.getElementById("touchEvent").innerHTML = "Touch End"; 
       event.preventDefault(); 
      }, false); 
      console.innerHTML = "event attached"; 
     } 
    </script> 
    <style type="text/css"> 
     html, body { 
      height:100%; 
      width:100%; 
      margin: 0; 
      background-color:red; 
     } 
     #map { 
      height: 300px; 
      width: 300px; 
      background-color:yellow; 
     } 
    </style> 
</head> 

<body> 
    <div id="map"></div> 
    <div id="touchCoord">Touch Coords</div> 
    <div id="touchEvent">Touch Evnt</div> 
    <div id="console">Console</div> 

</body> 

+1

我米不知道你是如何試圖做到這一點。當你說你已經用模擬器試過了,你是什麼意思?您是否正在運行Android應用程序(例如,使用各種「視圖」的「活動」),還是正在使用Android瀏覽器訪問網頁?如果您正在編寫實際的Android應用程序,請注意'WebView'不適用於'onTouchEvent'回調。其內置的系統可以在大於屏幕的頁面上與「MotionEvent」發生衝突,這樣就會出現不一致的行爲。 – 2010-06-07 10:35:40

+0

我在7in安卓平板電腦上也收到了這個問題,'touchend'事件永遠不會觸發..請參閱http://code.google.com/p/android/issues/detail?id=19827#makechanges – 2012-08-20 15:45:12

回答

6

這是網頁開發,所以我正在構建一個可以利用觸摸事件的網頁。

我想出了問題所在。

touchend事件被觸發時,event.touches[]數組爲空,所以引發了Javascript錯誤。這個事件被解僱了,但它沒有打印任何東西,因爲我試圖訪問未定義的數據。模擬器瀏覽器似乎沒有任何我找到的Javascript調試工具,甚至在發生Javascript錯誤時甚至沒有告訴我,所以花了我一段時間才弄清楚。

19

這就是你需要如何正確使用它。當手指進入屏幕時,捕捉起始點x,y。隨着手指移動,touchmove事件更新結尾x,y。完成後,觸發器會觸發 - 但是,它沒有觸摸數組,因此出現javascript錯誤。這就是爲什麼我們只用它來捕獲這是一個結束任務(手指離開屏幕),然後對它做出反應。 (在這種情況下,我發信息提醒。)

var gnStartX = 0; 
var gnStartY = 0; 
var gnEndX = 0; 
var gnEndY = 0; 

window.addEventListener('touchstart',function(event) { 
    gnStartX = event.touches[0].pageX; 
    gnStartY = event.touches[0].pageY; 
},false); 

window.addEventListener('touchmove',function(event) { 
    gnEndX = event.touches[0].pageX; 
    gnEndY = event.touches[0].pageY; 
},false); 

window.addEventListener('touchend',function(event) { 
    alert('START (' + gnStartX + ', ' + gnStartY + ') END (' + gnEndX + ', ' + gnEndY + ')'); 
},false); 
2
map.addEventListener ('touchend', function (event) { 
    var touch = event.changeTouches[0]; 
    ... 
} 
+0

這個解決方案對我來說很有用,謝謝 – 2016-01-26 15:07:41

31

對於任何人試圖弄清楚爲什麼touchend事件失蹤的Android V3和V4(也許還V2.3),還有很長的僅剛剛固定在V4.1(顯然)優秀的錯誤:

http://code.google.com/p/android/issues/detail?id=4549

http://code.google.com/p/android/issues/detail?id=19827

要解決這個bug你必須調用preventDefault()在touchstart或first touchmove事件上。當然,這會阻止本地滾動,因此您需要自己重新實現。

+13

這個bug在Android 4.3上也不是固定的。 – BairDev 2013-12-23 12:52:28

+4

在4.4.2中有同樣的問題。 – Rhyono 2014-03-27 00:54:51

+0

「當然,這可以防止本地滾動,所以您需要自己重新實現。」 < - 我該怎麼做? 首先,我有想法使用「e.preventDefault()」touchmove事件(使瀏覽器觸發touchmove和touchend),而不是手動觸發touchmove事件,但似乎沒有辦法實現滾動/ zooming ourselfes ... – lx222 2014-04-09 10:23:07

1

這發生在奇巧,並通過根據Android開發http://developer.android.com/guide/webapps/migrating.html#TouchCancel

對於較舊的Android版本的問題是由機器人沒有通過觸摸事件引起的,如果是的preventDefault不應用於touchstart事件的WebView處理touchcancel解決。這是硬編碼到數以百萬計的Android設備。 https://github.com/TNT-RoX/android-swipe-shim

+0

'touchcancel'在用戶開始滾動後立即觸發,並且無法知道用戶何時釋放他的手指,因爲「touchend」由於錯誤而未正確啓動。希望我會有一些時間來檢查你的android-swipe-shim,但是恐怕它不能檢測到「手指釋放」又名'touchend'。 – 2015-02-01 03:42:30

1

我是能夠通過從包含這樣的web視圖活性手動觸發touchend事件上ACTION_UP運動事件來解決這個問題:

//onCreate method 
webView.setOnTouchListener(new View.OnTouchListener() 
{ 
    @Override 
    public boolean onTouch(View view, MotionEvent motionEvent) 
    { 
     if(motionEvent.getAction() == MotionEvent.ACTION_UP) 
     { 
     webView.loadUrl("javascript:document.dispatchEvent(new CustomEvent('touchend'))"); 
     } 
     return false; 
    } 
}); 
+0

這是大膽的,但它的作品:)你救了我的一天,謝謝。 – 2015-11-25 09:15:26

2

我有同樣的問題,並且另外結合「touchcancel '事件解決了它。做了一些測試,當'touchend'沒有被解僱,那麼'touchcancel'事件就被解僱了。

var onTouchEnd = function(){ 
    console.log("touch end"); 
} 
document.addEventListener("touchend", onTouchEnd); 
document.addEventListener("touchcancel", onTouchEnd); 
+0

我可以確認這對於android 5來說,找到了相同的解決方案。 – wessel 2016-10-19 12:25:07

0

這裏的解決方案,以保持滾動啓用:

中的TouchMove處理程序添加一個preventDefault(),但在有條件的包裝它是檢查橫向滾動運動:

onTouchStart = function (e) {    // Save start position 
    startX = e.originalEvent.touches[0].pageX; 
    startY = e.originalEvent.touches[0].pageY; 
} 

onTouchMove = function (e) { 
    currentX = e.originalEvent.touches[0].pageX; 
    currentY = e.originalEvent.touches[0].pageY; 
    translateY = Math.abs(currentY - startY); 
    if (translateY < 10) { // If we are not (yet) scrolling vertically: 
    e.preventDefault() 
    } 
}