javascript - library - touch events jquery
El evento touchend no funciona en Android (9)
Empecé a buscar un desarrollo web móvil básico en Android y un guión 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 ?
Lo intenté en tres versiones del emulador (1.6, 2.1 y 2.2) y las tres se comportaron de la misma manera.
Gracias de antemano por cualquier ayuda que pueda darme.
Saludos, Colm
EDITAR - También he intentado esto usando el framework XUI y tengo el mismo problema, así que supongo que tengo un malentendido fundamental sobre cómo funciona esto ...
Prueba de mapa
<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>
Así es como debes usarlo 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, envío 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);
Es desarrollo web, así que estoy construyendo una página web que puede utilizar los eventos táctiles.
Me di cuenta de cuál era el problema.
Cuando se touchend
evento event.touches[]
matriz event.touches[]
está vacía, por lo que se event.touches[]
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.
Esto ocurre en KitKat y se resuelve mediante el manejo de touchcancel de acuerdo con android dev http://developer.android.com/guide/webapps/migrating.html#TouchCancel
Para las versiones anteriores de Android, el problema se debe a que Android no pasa eventos táctiles a la vista web si preventdefault no se aplica al evento touchstart. Esto está codificado en millones de dispositivos Android. github.com/TNT-RoX/android-swipe-shim
La TouchList siempre está vacía cuando se activa el evento touchend porque eliminaste todos los dedos de la pantalla :).
http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/
Para cualquiera que intente descubrir por qué los eventos de touchend faltan en Android v3 y v4 (tal vez también v2.3), hay un error pendiente que acaba de solucionarse en v4.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, debe invocar 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.
Pude solucionar el problema activando manualmente el evento touchend
evento de movimiento ACTION_UP
de la actividad que contiene el WebView de esta manera:
//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;
}
});
Tuve el mismo problema y, además, vinculando el evento ''touchcancel'' 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);
Aquí hay una solución para mantener el desplazamiento habilitado:
Agregue un preventDefault()
en el manejador touchMove, pero envuélvalo en un condicional que verifica 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()
}
}
map.addEventListener (''touchend'', function (event) {
var touch = event.changeTouches[0];
...
}