Je viens tout juste de commencer à étudier le développement Web mobile de base sur Android et à écrire un script de test pour étudier les événements tactiles. J'ai exécuté le code suivant dans l'émulateur Android et l'événement touchend ne se déclenche jamais. Quelqu'un peut-il me dire pourquoi?
J'ai essayé trois versions de l'émulateur (1.6, 2.1 et 2.2) et toutes les trois se comportent de la même manière.
Merci d'avance pour toute aide que vous pouvez me donner.
Salutations, Colm
EDIT - J'ai aussi essayé ceci en utilisant le framework XUI et j'ai le même problème, alors je suppose que j'ai un malentendu fondamental sur la façon dont ça marche ......
Test de la carte
<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>
Pour tous ceux qui essaient de comprendre pourquoi les événements tactiles manquent sur Android v3 et v4 (peut-être aussi v2.3), il existe un long bogue qui n'a été corrigé que dans la v4.1 (apparemment):
http://code.google.com/p/Android/issues/detail?id=4549
http://code.google.com/p/Android/issues/detail?id=19827
Pour contourner ce bogue, vous devez appeler preventDefault()
sur l'événement touchstart ou first touchmove. Bien sûr, cela empêche le défilement natif, vous devrez donc le ré-implémenter vous-même.
Voici comment vous devez l'utiliser correctement. Vous capturez le point de départ x, y lorsque le doigt passe à l'écran. Lorsque le doigt se déplace, l'événement touchmove met à jour une fin x, y. Une fois terminé, le touchend se déclenche - mais oui, il n’a pas de tableau de contacts, et donc une erreur javascript. C'est pourquoi nous ne l'utilisons que pour capturer qu'il s'agit d'une tâche finale (doigts sortis de l'écran), puis y réagir. (Dans ce cas, j'envoie une alerte informative.)
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);
Il s’agit d’un développement Web. Je construis donc une page Web qui peut utiliser les événements tactiles.
J'ai compris quel était le problème.
Lorsque l'événement touchend
est déclenché, le tableau event.touches[]
est vide. Une erreur Javascript est donc générée. L'événement était déclenché, mais il n'a rien imprimé, car j'essayais d'accéder à des données non définies. Le navigateur d'émulateur ne semble pas avoir d'outils de débogage Javascript que j'ai trouvé et ne m'a même pas dit quand une erreur Javascript s'est produite.
map.addEventListener ('touchend', function (event) {
var touch = event.changeTouches[0];
...
}
J'ai eu le même problème et en plus de lier l'événement 'touchcancel' l'a résolu. Est-ce que des tests ont été effectués et que «touchend» n'a pas été licencié, l'événement «touchcancel» a été déclenché.
var onTouchEnd = function(){
console.log("touch end");
}
document.addEventListener("touchend", onTouchEnd);
document.addEventListener("touchcancel", onTouchEnd);
La TouchList est toujours vide lorsque l'événement touchend est déclenché car vous avez supprimé tous les doigts de l'écran :).
http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/
Cela se produit sur KitKat et est résolu en traitant touchcancel selon Android dev http://developer.Android.com/guide/webapps/migrating.html#TouchCancel
Pour les versions plus anciennes d'Android, le problème est dû au fait qu'aucun événement tactile n'a été transmis par Android à WebView si l'option preventdefault n'est pas appliquée à l'événement touchstart. Ceci est codé en dur dans des millions d'appareils Android. https://github.com/TNT-RoX/Android-swipe-shim
J'ai pu résoudre le problème en déclenchant manuellement l'événement touchend
sur l'événement de mouvement ACTION_UP
à partir de l'activité contenant la vue Web, comme ceci:
//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;
}
});
Voici une solution pour garder le défilement activé:
Ajoutez une preventDefault()
dans le gestionnaire touchMove, mais enveloppez-le dans une condition conditionnant le mouvement de défilement latéral:
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()
}
}