Android browser: touchcancel being fired althought touchmove has preventDefault
Asked Answered
D

3

15

I'm trying to build a Webpage that senses the touch from the user and drags and object along the canvas.

So I'm doing something like this:

var touchStart = function(e) {
    e.preventDefault();
    // Do stuff
}
var touchMove = function(e) {
    e.preventDefault();
    console.log("Touch move");
    // Move objs
}
var touchEnd = function(e) {
    e.preventDefault();
    console.log("Touch start!");
    // clean up stuff
}
var touchCancel = function(e) {
    e.preventDefault();

    // Oh NO touch cancel!
    console.log("Touch cancel!");

}
bindElemOrig.addEventListener('touchstart', touchStart, false);
bindElemOrig.addEventListener('touchmove', touchStart, false);
bindElemOrig.addEventListener('touchend', touchStart, false);
bindElemOrig.addEventListener('touchcancel', touchStart, false);

It works fine until some point.

The problem is that as soon as I load too many objs, it seems to me that the touchmove takes too long to respond, and touchcancel gets triggered. The problem is that as soon as touchcancel get triggered I don't receive any more touchmoves events, and I cannot sense the movement anymore.

Did anyone face this problem? I know about the bug in Android where you must call preventDefault (touchend event in ios webkit not firing?) but on this case it seems that it is not working because of the memory burden.

Thank you!

Dylan answered 11/4, 2013 at 8:37 Comment(3)
I'm experiencing the same problem on Android 2.3. Android 4+ seems to be ok. Did you find anything on this topic?Ana
@dioslaska shim @ github.com/TNT-RoX/android-swipe-shimStentorian
For future reference, the answer here works perfectly: https://mcmap.net/q/826257/-html5-android-touchcancelJernigan
R
3

like this

var touchMove = function(e) {
    e.preventDefault();
    setTimeout(function(){
        console.log("Touch move");
    // Move objs

    })
}

use setTimeout to wrap you logic in touchmove can solve this problem

Rockaway answered 14/10, 2014 at 7:41 Comment(0)
L
2

This problem may be due to a bug (feature?) in Chrome/Android. See this bug report.

This test demonstrates the behavior (JSFiddle):

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <script>
      var delay = 200;

      var haltEvent = function(event) {
        event.preventDefault();
        event.stopPropagation();
      };

      var pause = function() {
        var startTime = new Date().getTime();

        while (new Date().getTime() < startTime + delay);
      };

      window.addEventListener('load', function() {
        var target = document.querySelector('#target');
        var status = document.querySelector('#status');

        target.addEventListener('touchstart', function(event) {
          haltEvent(event);
          status.innerHTML = '[touchstart]';
        }, true);

        target.addEventListener('touchmove', function(event) {
          pause();
          haltEvent(event);
          status.innerHTML = '[touchmove]';
        }, true);

        target.addEventListener('touchend', function(event) {
          status.innerHTML = '[touchend]'; 
        }, true);

        target.addEventListener('touchcancel', function(event) {
          status.innerHTML = '[touchcancel]'; 
        }, true);
      });
    </script>
    <style>
      #target {
        background-color: green;
        height: 300px;
      }

      #status {
        text-align: center;
      }
    </style>
  </head>
  <body>
    <div id="target"></div>
    <p id="status">[]</p>
  </body>
</html>

I don't find the touchcancel event to be fired randomly. Instead, it is fired whenever it takes ~200 ms to return from a touchmove event handler.

Lately answered 18/7, 2013 at 16:30 Comment(0)
H
0

Touchcancel is specifically designed to take control of touch events and perform regular browser actions such as pan or zoom after a very small touch and move action (nearly 20px, depending on browser).

Your only options are to either:

  1. Switch to Pointer Events and use the touch-action CSS property as explained here to prevent pointercancel from firing (recommended but requires Android 5+)
  2. Add event.preventDefault() inside your touchmove event handler, but this will also disable any default actions like scroll, pan, zoom, etc.

You cannot attemp to cancel or preventDefault() inside a touchcancel function because it will be too late for that; the browser has already stopped listening to the touchmove event. This is by design, not a bug.

Hodometer answered 6/10, 2017 at 2:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.