touchend事件在Android上不能运行

时间:2021-04-25 00:18:37

I've just started looking at doing some basic mobile web development on the android and an writing a test script to investigate the touch events. I've run the following code in the android emulator, and the touchend event never gets fired. Can anyone tell me why ?

我刚刚开始研究在android上进行一些基本的移动web开发,并编写一个测试脚本来研究触摸事件。我在android模拟器中运行了以下代码,touchend事件从未被触发。谁能告诉我为什么吗?

I've tried in three versions of the emulator (1.6, 2.1 and 2.2) and all three behave in the same way.

我已经在模拟器的三个版本(1.6、2.1和2.2)中尝试过,这三个版本的行为都是一样的。

Thanks in advance for any help you can give me.

谢谢你给我的任何帮助。

Cheers, Colm

欢呼,投资银行部

EDIT - I've also tried this using the XUI framework and have the same problem so I'm guessing I have a fundamental misunderstanding of how this stuff works ......

编辑-我也尝试过使用XUI框架,也有同样的问题,所以我猜我对这个东西的工作原理有一个根本性的误解……

Map Test

地图测验

    <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>

9 个解决方案

#1


31  

For anyone trying to figure out why touchend events are missing on Android v3 and v4 (maybe also v2.3), there is a long outstanding bug which only just got fixed in v4.1 (apparently):

对于任何试图弄明白为什么在Android v3和v4(也可能是v2.3)中缺少touchend事件的人来说,有一个很长的未完成的bug,它只是在v4.1中被修复了(很明显):

http://code.google.com/p/android/issues/detail?id=4549

http://code.google.com/p/android/issues/detail?id=4549

http://code.google.com/p/android/issues/detail?id=19827

http://code.google.com/p/android/issues/detail?id=19827

To workaround this bug you have to call preventDefault() on either the touchstart or first touchmove event. Of course, this prevents the native scrolling, so you will need to re-implement that yourself.

要解决这个bug,您必须在touchstart或第一次touchmove事件中调用preventDefault()。当然,这可以防止本机滚动,因此您需要自己重新实现它。

#2


19  

This is how you need to use it properly. You capture the starting x,y when the finger goes to the screen. As the finger moves across, the touchmove event updates an ending x,y. When finished, the touchend fires -- but yes, it doesn't have a touches array, and thus a javascript error. This is why we only use it for capturing that this is an ending task (fingers left the screen) and then react to it. (In this case, I send an informative alert.)

这就是正确使用它的方法。当手指进入屏幕时,你捕捉开始的x,y。当手指移动时,touchmove事件更新一个结尾x,y。完成后,touchend将触发——但是是的,它没有一个触摸数组,因此会出现一个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


6  

It's web development, so I am building a webpage that can utilize the touch events.

这是网页开发,所以我正在构建一个可以利用触摸事件的网页。

I figured out what the problem was.

我弄明白了问题所在。

When the touchend event is fired the event.touches[] array is empty, so a Javascript error is thrown. The event was being fired, but it didn't print anything out, because I was attempting to access undefined data. The emulator browser doesn't seem to have any Javascript debugging tools that I have found, and didn't even tell me when a Javascript error occurred, so it took me a while to figure it out.

当touchend事件触发事件。触摸[]数组为空,因此会抛出一个Javascript错误。事件正在被触发,但它没有输出任何内容,因为我试图访问未定义的数据。仿真器浏览器似乎没有我找到的任何Javascript调试工具,甚至在Javascript错误发生时都没有告诉我,所以我花了一段时间才弄明白。

#4


2  

The TouchList is always empty when touchend event is fired because you removed all fingers from the screen :).

当触发touchend事件时,TouchList总是空的,因为您从屏幕上删除了所有的手指:)。

http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/

http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/

#5


2  

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

#6


2  

I had the same problem and additionally binding the 'touchcancel' event solved it. Did some testing and when 'touchend' wasn't fired, then the 'touchcancel' event fired instead.

我遇到了同样的问题,另外绑定“touchcancel”事件解决了这个问题。做了一些测试,当“touchend”没有被触发时,“touchcancel”事件反而被触发。

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

#7


1  

This occurs on KitKat and is solved by handling touchcancel according to android dev http://developer.android.com/guide/webapps/migrating.html#TouchCancel

这发生在KitKat上,通过根据android dev http://developer.android.com/guide/webapps/migrating.html# touchcancel处理touchcancel来解决

For older android versions the problem is caused by android no passing touch events to webview if preventdefault is not applied to the touchstart event. This is hard-coded into millions of android devices. https://github.com/TNT-RoX/android-swipe-shim

对于较老的android版本,如果preventdefault没有应用于touchstart事件,那么这个问题是由android no向webview传递触摸事件引起的。这是硬编码到数以百万计的android设备。https://github.com/TNT-RoX/android-swipe-shim

#8


1  

I was able to fix the problem by triggering the touchend event manually on ACTION_UP motion event from the activity that contains the WebView like this:

我可以通过从包含WebView的活动中手动触发ACTION_UP动作事件的touchend事件来解决这个问题:

//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


0  

Here a solution to keep scrolling enabled:

这里有一个解决方案来保持滚动启用:

Add a preventDefault() in the touchMove handler, but wrap it in a conditional that checks for lateral scroll movement:

在touchMove处理程序中添加preventDefault(),但将其封装在检查横向滚动移动的条件中:

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

#1


31  

For anyone trying to figure out why touchend events are missing on Android v3 and v4 (maybe also v2.3), there is a long outstanding bug which only just got fixed in v4.1 (apparently):

对于任何试图弄明白为什么在Android v3和v4(也可能是v2.3)中缺少touchend事件的人来说,有一个很长的未完成的bug,它只是在v4.1中被修复了(很明显):

http://code.google.com/p/android/issues/detail?id=4549

http://code.google.com/p/android/issues/detail?id=4549

http://code.google.com/p/android/issues/detail?id=19827

http://code.google.com/p/android/issues/detail?id=19827

To workaround this bug you have to call preventDefault() on either the touchstart or first touchmove event. Of course, this prevents the native scrolling, so you will need to re-implement that yourself.

要解决这个bug,您必须在touchstart或第一次touchmove事件中调用preventDefault()。当然,这可以防止本机滚动,因此您需要自己重新实现它。

#2


19  

This is how you need to use it properly. You capture the starting x,y when the finger goes to the screen. As the finger moves across, the touchmove event updates an ending x,y. When finished, the touchend fires -- but yes, it doesn't have a touches array, and thus a javascript error. This is why we only use it for capturing that this is an ending task (fingers left the screen) and then react to it. (In this case, I send an informative alert.)

这就是正确使用它的方法。当手指进入屏幕时,你捕捉开始的x,y。当手指移动时,touchmove事件更新一个结尾x,y。完成后,touchend将触发——但是是的,它没有一个触摸数组,因此会出现一个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


6  

It's web development, so I am building a webpage that can utilize the touch events.

这是网页开发,所以我正在构建一个可以利用触摸事件的网页。

I figured out what the problem was.

我弄明白了问题所在。

When the touchend event is fired the event.touches[] array is empty, so a Javascript error is thrown. The event was being fired, but it didn't print anything out, because I was attempting to access undefined data. The emulator browser doesn't seem to have any Javascript debugging tools that I have found, and didn't even tell me when a Javascript error occurred, so it took me a while to figure it out.

当touchend事件触发事件。触摸[]数组为空,因此会抛出一个Javascript错误。事件正在被触发,但它没有输出任何内容,因为我试图访问未定义的数据。仿真器浏览器似乎没有我找到的任何Javascript调试工具,甚至在Javascript错误发生时都没有告诉我,所以我花了一段时间才弄明白。

#4


2  

The TouchList is always empty when touchend event is fired because you removed all fingers from the screen :).

当触发touchend事件时,TouchList总是空的,因为您从屏幕上删除了所有的手指:)。

http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/

http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/

#5


2  

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

#6


2  

I had the same problem and additionally binding the 'touchcancel' event solved it. Did some testing and when 'touchend' wasn't fired, then the 'touchcancel' event fired instead.

我遇到了同样的问题,另外绑定“touchcancel”事件解决了这个问题。做了一些测试,当“touchend”没有被触发时,“touchcancel”事件反而被触发。

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

#7


1  

This occurs on KitKat and is solved by handling touchcancel according to android dev http://developer.android.com/guide/webapps/migrating.html#TouchCancel

这发生在KitKat上,通过根据android dev http://developer.android.com/guide/webapps/migrating.html# touchcancel处理touchcancel来解决

For older android versions the problem is caused by android no passing touch events to webview if preventdefault is not applied to the touchstart event. This is hard-coded into millions of android devices. https://github.com/TNT-RoX/android-swipe-shim

对于较老的android版本,如果preventdefault没有应用于touchstart事件,那么这个问题是由android no向webview传递触摸事件引起的。这是硬编码到数以百万计的android设备。https://github.com/TNT-RoX/android-swipe-shim

#8


1  

I was able to fix the problem by triggering the touchend event manually on ACTION_UP motion event from the activity that contains the WebView like this:

我可以通过从包含WebView的活动中手动触发ACTION_UP动作事件的touchend事件来解决这个问题:

//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


0  

Here a solution to keep scrolling enabled:

这里有一个解决方案来保持滚动启用:

Add a preventDefault() in the touchMove handler, but wrap it in a conditional that checks for lateral scroll movement:

在touchMove处理程序中添加preventDefault(),但将其封装在检查横向滚动移动的条件中:

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