2010-06-07 49 views
32

Acabo de comenzar a buscar un desarrollo web móvil básico en Android y un script de prueba para investigar los eventos táctiles. He ejecutado el siguiente código en el emulador de Android, y el evento touchend nunca se dispara. Puede alguien decirme por que ?touchend event no funciona en Android

He intentado en tres versiones del emulador (1.6, 2.1 y 2.2) y las tres se comportan de la misma manera.

Gracias de antemano por cualquier ayuda que pueda darme.

Saludos, Colm

EDITAR - También he intentado esto con el marco XUI y tienen el mismo problema, así que supongo que tengo un malentendido fundamental de cómo funciona esta cosa ......

Mapa prueba

<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' No estoy seguro de cómo estás tratando de hacer esto. Cuando dijiste que lo probaste con el emulador, ¿qué quisiste decir? ¿Estás ejecutando una aplicación de Android (por ejemplo, una "Actividad" que utiliza varias "Vistas") o estás accediendo a una página web con el navegador Android? Si está escribiendo una aplicación real de Android, tenga en cuenta que 'WebView' no funciona bien con las devoluciones de llamada' onTouchEvent'. Su sistema integrado para desplazarse en una página más grande que la pantalla entra en conflicto con 'MotionEvent's para que tengas un comportamiento incoherente. –

+0

Estoy obteniendo esto también en una tableta Android de 7 pulgadas, el evento 'touchend' nunca se dispara .. vea http://code.google.com/p/android/issues/detail?id=19827#makechanges –

Respuesta

6

Es desarrollo web, así que estoy construyendo una página web que puede utilizar los eventos táctiles.

Descubrí cuál era el problema.

Cuando se activa el evento touchend, la matriz event.touches[] está vacía, por lo que se produce un error de Javascript. El evento fue despedido, pero no se imprimió nada porque estaba intentando acceder a datos no definidos. El navegador del emulador no parece tener ninguna herramienta de depuración de JavaScript que he encontrado, y ni siquiera me dijo cuándo ocurrió un error de Javascript, por lo que me tomó un tiempo averiguarlo.

19

Ésta es la forma en que hay que usarla correctamente. Capturas el comienzo x, y cuando el dedo va a la pantalla. A medida que el dedo se mueve, el evento touchmove actualiza una terminación x, y. Cuando termina, el touchend se dispara, pero sí, no tiene una matriz de toques, y por lo tanto un error de javascript. Es por eso que solo lo usamos para capturar que se trata de una tarea final (los dedos abandonan la pantalla) y luego reaccionamos a ella. (En este caso, puedo enviar una alerta informativa.)

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

Esta solución funcionó para mí, gracias –

31

para cualquiera que trate de averiguar por qué eventos touchend faltan en V3 y V4 Android (tal vez también v2.3), hay una larga error excepcional que sólo acaba de ser corregido en la versión 4.1 (aparentemente):

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

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

para solucionar este error tiene que llamar preventDefault() en el evento touchstart o first touchmove. Por supuesto, esto evita el desplazamiento nativo, por lo que tendrá que volver a implementarlo usted mismo.

+13

Este error no es fixid en Android 4.3, también. – BairDev

+4

Tuve el mismo problema en 4.4.2. – Rhyono

+0

"Por supuesto, esto evita el desplazamiento nativo, por lo que deberá volver a implementarlo usted mismo". <- ¿cómo haría eso? Primero tuve Idea para usar "e.preventDefault()" para touchmove-events (para hacer que el Navegador active y cambie el tacto) y luego activar el evento touchmove manualmente, pero parece que no hay forma de implementar el desplazamiento/acercarnos a nosotros mismos ... – lx222

1

Esto se produce en KitKat y se resuelve mediante la manipulación touchcancel acuerdo con dev androide http://developer.android.com/guide/webapps/migrating.html#TouchCancel

Para las versiones más antiguas de Android el problema es causado por el androide no hay eventos de toque que pasa a WEBVIEW si preventDefault no se aplica al caso touchstart. Esto está codificado en millones de dispositivos Android. https://github.com/TNT-RoX/android-swipe-shim

+0

'touchcancel' se activa justo después de que el usuario comienza a desplazarse y no hay manera de saber cuándo el usuario soltó su dedo ya que' touchend' no se disparó correctamente debido a la falla. Espero tener algo de tiempo para revisar tu android-swipe-shim, pero me temo que tampoco podrá detectar "finger release" aka 'touchend'. –

1

I fue capaz de solucionar el problema mediante la activación del evento touchend manualmente en ACTION_UP evento de movimiento a partir de la actividad que contiene el WebView como esto:

//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 audaz pero funciona :) me salvaste el día, gracias. –

2

I tenían el mismo problema y, además, la unión del 'touchcancel 'evento lo resolvió. Hizo algunas pruebas y cuando 'touchend' no se activó, el evento 'touchcancel' se activó.

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

Puedo confirmar esto para Android 5, encontré la misma solución. – wessel

0

Aquí una solución para mantener el desplazamiento permitido:

Añadir un preventDefault() en el controlador TouchMove, pero lo envuelve en un condicional que los controles para el movimiento de desplazamiento lateral:

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