Android browser touch events stop display being updated inc. canvas/elements - How to work around?
Asked Answered
P

4

9

On some android's native browser touching the page seems to stop the display from being updated until the finger is released. This occurs for both html element based animation (switching classes) and for canvas based animation. It does not however stop normal js execution and other events are fired as normal. On devices with this problem the dolphin browser also seems effected (not firefox though).

Touchstart/move both have preventDefault() fired as well as stopPropergation(), cancelBubble = true; and e.returnValue = false;. In the CSS webkit selection has also been disabled. The page will not scroll.

A similar question has been asked here: Does Android browser lock DOM on touchStart?

but I'd like to find out if this behaviour can be overcome, or at least to discover what devices will be effected by the problem, is it a device or version android issue? If you cannot answer the question running the demo and reporting your experience along with your device model and useragent (displayed at bottom of demo page) as a comment might help others or myself answer the question.

Here is a demo and steps to reproduce the behaviour. A QR code for the link can be found here https://s3-eu-west-1.amazonaws.com/canvas-test-pd/tmp.png.

https://s3-eu-west-1.amazonaws.com/canvas-test-pd/index.html

The web page has a canvas at the top and a div with a background image at the bottom. Every second the canvas is cleared and a different image displayed and the div has it's class switched (both toggle between 0 and 1 pngs). Once this has toggled a few times place your finger on the canvas (the top grey box) and hold it there. Wait to see if the animation continues (sometimes it will once or twice then stops) and if there are any visual distortions.

Update It seems that the Galaxy Tab running 3.2 requires handlers for touchstart/end of document, not just required divs for the screen to continue updating the display. Thanks jimpic.

I'm starting to believe it's an issue caused by manufacturers skins, although this is difficult to prove.

Posture answered 20/4, 2012 at 12:32 Comment(1)
I'll start: Display does not update until finger lifted. Device Huawei Ascert G300: mozilla/5.0 (linux; u; android 2.3.6; en-gb; u8815 build/huaweiu8815c02b882) applewebkit/533.1 (khtml, like gecko) version/4.0 mobile safari/533.1Posture
S
7

I can't really tell you why this is happening, but I came across a similar problem, when registering for documents touch events. When I registered for only touch move events, I had exactly the same problem you are experiencing, however when I registered for touchstart too, it suddenly worked. In your case, just add the following lines to your main.js

function touchHandlerDummy(e)
{
    e.preventDefault();
    return false;
}
document.addEventListener("touchstart", touchHandlerDummy, false);
document.addEventListener("touchmove", touchHandlerDummy, false);
document.addEventListener("touchend", touchHandlerDummy, false);

Works on my Galaxy Tab. Hope this is what you were trying to do.

Sensate answered 8/5, 2012 at 9:11 Comment(5)
Thanks for responding, but the demo code already uses preventDefault and returns false on touchstart and touchmove. Is the demo page working on your Tab? And which version of android are you using (subversion as well please, i.e. x.y.z)? Thanks againPosture
I know it already uses preventDefault, but only for selected elements, not the complete document, maybe that's the problem. Just add the lines above to your main.js in your jQuery ready() function and it will work. It did not work on my Galaxy Tab before, but after - so give it a try :) (Android version 3.2) I made a copy of your complete project and added the above lines. It works now.Sensate
Originally on this demo I did have handlers for touch events of document, but removed them to allow copy&paste of user agent. It doesn't solve the problem on my device (Huawei g300), but it's interesting that you witness that behaviour on your 3.2 Tab. Without handlers for document touchstart/end it DOES work on a Galaxy Ace 2.3.3 and the android simulator 2.3.3. I haven't tried 3.2 on the sim - I will later and compare. I'm starting to think this might be an issue with the differing skins manufacturers apply. I'll update the question with your information, thank you.Posture
you only need to preventdefault on touchstartChilung
This code completely disables any type of scrolling in any direction whatsoever on both Android 2.3 and Android 4.1, why would anyone use this?Conceal
D
3

I had the very same problem. Magically enough, the problem disappeared completely when I added the following line to the <header> section:

<meta name="viewport" content="width=device-width">
Deficient answered 21/12, 2013 at 18:19 Comment(2)
This solution worked for me. But now the user can zoom the page, which I don't want. My original meta tag looked like this: <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"> . Playing around with it, I found I can set maximum-scale to 1.1. Now touchstart works, and the user can zoom the page, but only a tiny bit. My meta tage looks like this now: <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.1">Sage
Wow, this was it! Talk about an obscure issue! @BrianEphraim If you don't need scrolling on your page, you can also set a touchmove event listener on document.body and call preventDefault on the event. That'll prevent zooming.Rost
F
1

Answers here helped me a lot.

My solution is simply combination of what has been mentioned here, so if you want:
1. "drag and drop" on Samsung Galaxy S2 native browser (Android 4.1.2)
2. disable user scaling the page (viewport set to no scaling)

<head>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.01">
    <script>
        window.addEventListener("load", function() {
            function onTouchPreventDefault(event) { event.preventDefault(); };
            document.addEventListener("touchmove", onTouchPreventDefault, false);
            document.addEventListener("touchstart", onTouchPreventDefault, false);
        }, false);
    </script>
</head>
  1. Viewport
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.01">

    • unfortunately user can still zoom the page in a little bit, 1.01 is the smallest value that does the job
  2. Disable pinch to zoom
    document.addEventListener("touchmove", function (event) { event.preventDefault(); }, false);

    • this disables pinch to zoom
  3. Disable double tap to zoom
    document.addEventListener("touchstart", function (event) { event.preventDefault(); }, false); //OR document.addEventListener("touchend", function (event) { event.preventDefault(); }, false);

    • this disables double tap to zoom, you can choose if you want to use touchstart or touchend (or both) for this purpouse
Frei answered 20/5, 2014 at 13:20 Comment(0)
E
0

this will do the trick :)

function touchHandlerDummy(e) { e.preventDefault(); return false; } document.addEventListener("touchmove", touchHandlerDummy, false);
Eagan answered 25/11, 2012 at 11:0 Comment(1)
This has already been suggested and discussed in jimpic's answer. You also always need to handle touchstart as well when overriding regular behaviour.Posture

© 2022 - 2024 — McMap. All rights reserved.