touchend 事件在 Android 上不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2987706/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
touchend event doesn't work on Android
提问by Protos
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 上做一些基本的移动网络开发,并编写一个测试脚本来调查触摸事件。我已经在 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>
回答by SystemParadox
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 事件的人来说,有一个长期未解决的错误,它只是在 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.
要解决此错误,您必须调用preventDefault()
touchstart 或 first touchmove 事件。当然,这会阻止本机滚动,因此您需要自己重新实现它。
回答by Volomike
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 会触发——但是是的,它没有 touches 数组,因此会出现 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);
回答by Protos
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
事件被触发时,event.touches[]
数组为空,因此抛出一个 Javascript 错误。事件被触发,但它没有打印任何内容,因为我试图访问未定义的数据。模拟器浏览器似乎没有我找到的任何 Javascript 调试工具,甚至没有告诉我何时发生 Javascript 错误,所以我花了一段时间才弄清楚。
回答by dplehati
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-gesting-on-the-iphone/
回答by kenshou.html
map.addEventListener ('touchend', function (event) {
var touch = event.changeTouches[0];
...
}
回答by Humppak?r?j?t
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);
回答by Raymundus
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:
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()
}
}
回答by tnt-rox
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 没有将触摸事件传递给 webview 引起的。这被硬编码到数以百万计的安卓设备中。https://github.com/TNT-RoX/android-swipe-shim
回答by Petr Peller
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:
我能够通过touchend
在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;
}
});