2010-06-07 3 views
32

Ich habe gerade angefangen zu tun, einige grundlegende mobile Web-Entwicklung auf dem Android und ein Schreiben ein Testskript, um die Touch-Ereignisse zu untersuchen. Ich habe den folgenden Code im Android-Emulator ausgeführt, und das touchend-Ereignis wird nie ausgelöst. Kann mir jemand sagen warum?touchend Ereignis funktioniert nicht auf Android

Ich habe in drei Versionen des Emulators (1.6, 2.1 und 2.2) versucht und alle drei verhalten sich auf die gleiche Weise.

Vielen Dank im Voraus für jede Hilfe, die Sie mir geben können.

Cheers, Colm

EDIT - Ich habe auch dies mit der XUI Rahmen versucht und haben das gleiche Problem, so das Zeug funktioniert Ich vermute, ich ein grundlegendes Missverständnis, wie haben ......

Map-Test

<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

I‘ Ich bin mir nicht sicher, wie Sie das versuchen. Als du gesagt hast, dass du es mit dem Emulator ausprobiert hast, was meintest du? Führen Sie eine Android-Anwendung (z. B. eine "Aktivität", die verschiedene "Ansichten" verwendet) oder greifen Sie mit dem Android-Browser auf eine Webseite zu? Wenn Sie eine tatsächliche Android-Anwendung schreiben, beachten Sie, dass 'WebView' nicht gut mit den' onTouchEvent'-Callbacks funktioniert. Das eingebaute System zum Schwenken auf einer Seite, die größer als der Bildschirm ist, steht in Konflikt mit 'MotionEvent', so dass Sie inkonsistentes Verhalten bekommen. –

+0

Ich bekomme das auch in einem 7in Android Tablet, 'touchend' Ereignis wird nie ausgelöst .. siehe http://code.google.com/p/android/issues/detail?id=19827#makechanges –

Antwort

6

Es ist Web-Entwicklung, also baue ich eine Webseite, die die Berührungsereignisse nutzen kann.

Ich habe herausgefunden, was das Problem war. Wenn das Ereignis touchend ausgelöst wird, ist das event.touches[] Array leer, so dass ein Javascript-Fehler ausgelöst wird. Das Ereignis wurde ausgelöst, es wurde jedoch nichts ausgedruckt, weil ich versuchte, auf nicht definierte Daten zuzugreifen. Der Emulator-Browser scheint keine JavaScript-Debugging-Tools zu haben, die ich gefunden habe, und hat mir nicht einmal gesagt, wenn ein Javascript-Fehler auftrat, also brauchte ich eine Weile, um es herauszufinden.

19

Dies ist, wie Sie es richtig verwenden müssen. Sie fangen den Start x, y ein, wenn der Finger auf den Bildschirm geht. Während sich der Finger bewegt, aktualisiert das Ereignis touchmove eine Endung x, y. Wenn es fertig ist, feuert der Touchend - aber ja, es hat keine Berührungen Array und damit einen Javascript-Fehler. Deshalb verwenden wir es nur zum Erfassen, dass dies eine End-Aufgabe ist (Finger verlassen den Bildschirm) und reagieren darauf. (In diesem Fall schicke ich einen informativen Alarm.)

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

Diese Lösung funktionierte für mich, danke –

31

Für jeden, der versucht, herauszufinden, warum touchend Ereignisse auf Android v3 und v4 fehlen (vielleicht auch v2.3), gibt es eine lange herausragende Fehler, der nur bekam in v4.1 nur feste (scheinbar):

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

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

diesen Fehler zu umgehen müssen Sie rufen preventDefault() entweder beim Touchstart oder beim ersten Touchmove-Ereignis. Dies verhindert natürlich das native Scrollen, Sie müssen das also selbst umsetzen.

+13

Dieser Fehler ist nicht auf Android 4.3 behoben. – BairDev

+4

Hatte das gleiche Problem in 4.4.2. – Rhyono

+0

"Natürlich verhindert dies das native Scrollen, also müssen Sie das selbst umsetzen." <- wie würde ich das machen ??? Zuerst hatte ich die Idee, "e.preventDefault()" für touchmove-events zu verwenden (um den Browser touchmove und touchend zu aktivieren) und dann das touchmove-event manuell auszulösen, aber es scheint, zooming ourselfes ... – lx222

1

Dies geschieht auf KitKat und wird durch den Umgang mit touchcancel nach android dev http://developer.android.com/guide/webapps/migrating.html#TouchCancel

Für ältere Android-Versionen das Problem von Android kein Vergehen Berührungsereignisse verursacht wird, gelöst WebView wenn prevent nicht auf die Berührungsstartereignis angewendet wird. Dies ist in Millionen von Android-Geräten fest codiert. https://github.com/TNT-RoX/android-swipe-shim

+0

'touchcancel' wird ausgelöst, nachdem der Benutzer scrollt und es gibt keine Möglichkeit zu wissen, wann der Benutzer seinen Finger losgelassen hat, da' touchend' aufgrund des Fehlers nicht korrekt ausgelöst wurde. Hoffentlich habe ich etwas Zeit, um Ihre Android-Swipe-Shim zu überprüfen, aber ich fürchte, es wird nicht in der Lage sein, "Finger Release" aka 'touchend' entweder zu erkennen. –

1

Ich war in der Lage, das Problem zu beheben, indem das touchend Ereignis manuell auf ACTION_UP Bewegungsereignis aus der Tätigkeit Auslösung, die die WebView wie folgt enthält:

//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

es ist fett, aber es funktioniert :) Sie haben meinen Tag gerettet, danke. –

2

Ich hatte das gleiche Problem und zusätzlich die Bindung das ‚touchcancel 'Ereignis löste es. Wurden einige Tests durchgeführt und wurde 'touchend' nicht ausgelöst, wurde stattdessen das Ereignis 'touchcancel' ausgelöst.

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

Ich kann dies für Android 5 bestätigen, fand die gleiche Lösung. – wessel

0

Hier ist eine Lösung Scrollen halten aktiviert:

eine preventDefault() im Handler touchmove hinzufügen, aber es in einer bedingten wickeln, dass die Kontrollen für die seitliche Scroll-Bewegung:

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() 
    } 
}