Событие touchhend не работает на Android

Я только начал изучать базовую мобильную веб-разработку на андроиде и написать тест script для исследования событий касания. Я запустил следующий код в эмуляторе Android, и событие touchhend никогда не запускается. Может ли кто-нибудь сказать мне, почему?

Я пробовал в трех версиях эмулятора (1.6, 2.1 и 2.2), и все три ведут себя одинаково.

Заранее благодарим за любую помощь, которую вы можете мне дать.

Cheers, Колм

EDIT. Я также пробовал это с использованием инфраструктуры 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 версии 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

Чтобы обойти эту ошибку, вы должны называть preventDefault() на сенсорном экране или в первом событии touchmove. Конечно, это предотвращает естественную прокрутку, поэтому вам нужно будет повторно реализовать это самостоятельно.

Ответ 2

Вот как вам нужно правильно его использовать. Вы фиксируете начальный 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);

Ответ 3

Это веб-разработка, поэтому я создаю веб-страницу, которая может использовать события касания.

Я понял, в чем проблема.

Когда событие touchend запущено, массив event.touches[] пуст, поэтому возникает ошибка Javascript. Событие запускалось, но ничего не выдавало, потому что я пытался получить доступ к данным undefined. У браузера эмулятора, похоже, нет каких-либо инструментов отладки Javascript, которые я нашел, и даже не сказал мне, когда произошла ошибка Javascript, поэтому мне потребовалось некоторое время, чтобы понять это.

Ответ 5

map.addEventListener ('touchend', function (event) {
    var touch = event.changeTouches[0];
    ...
}

Ответ 6

У меня была та же проблема, и дополнительно связать событие "touchcancel" решила его. Было ли какое-то тестирование и когда "touchhend" не был уволен, тогда вместо этого произошло событие "touchcancel".

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

Ответ 7

Это происходит на KitKat и решается путем обработки touchcancel в соответствии с android dev http://developer.android.com/guide/webapps/migrating.html#TouchCancel

Для старых версий для Android проблема связана с тем, что андроид не передает события касания к веб-просмотру, если preventdefault не применяется к событию touchstart. Это жестко закодировано в миллионы устройств Android. https://github.com/TNT-RoX/android-swipe-shim

Ответ 8

Я смог устранить проблему, вызвав событие touchend вручную в событии motion ACTION_UP из активности, которая содержит WebView, как это:

//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;
   }
});

Ответ 9

Здесь разрешено поддерживать прокрутку:

Добавьте preventDefault() в обработчик touchMove, но оберните его в условное выражение, которое проверяет движение боковой прокрутки:

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