web-dev-qa-db-ja.com

touchendイベントはAndroidでは機能しません

Androidでいくつかの基本的なモバイルWeb開発を行い、タッチイベントを調査するためのテストスクリプトを書くことを検討し始めました。 Androidエミュレーターで次のコードを実行しましたが、touchendイベントは発生しません。誰もその理由を教えてもらえますか?

エミュレータの3つのバージョン(1.6、2.1、2.2)で試しましたが、3つとも同じように動作します。

助けてくれてありがとう。

乾杯、コルム

編集-私も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>
32
Protos

タッチエンドイベントが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

このバグを回避するには、touchstartイベントまたは最初のtouchmoveイベントでpreventDefault()を呼び出す必要があります。もちろん、これによりネイティブのスクロールが防止されるため、自分で再実装する必要があります。

31
SystemParadox

これは、適切に使用する方法です。指が画面に移動すると、開始X、Yをキャプチャします。指が移動すると、touchmoveイベントは終了x、yを更新します。終了すると、タッチエンドが起動しますが、はい、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);
20
Volomike

これはWeb開発なので、タッチイベントを利用できるWebページを構築しています。

私は問題が何であるかを理解しました。

touchendイベントが発生すると、event.touches[]配列が空なので、Javascriptエラーがスローされます。イベントは発生していましたが、未定義のデータにアクセスしようとしたため、何も出力されませんでした。エミュレーター・ブラウザーには、私が見つけたJavascriptデバッグ・ツールがないようで、Javascriptエラーがいつ発生したかさえ教えてくれなかったので、それを理解するのに時間がかかりました。

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

私は同じ問題を抱えており、さらに「touchcancel」イベントをバインドすることで解決しました。いくつかのテストを行い、「touchend」が発生しなかった場合、代わりに「touchcancel」イベントが発生しました。

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

画面からすべての指を削除したため、touchendイベントが発生すると、TouchListは常に空になります:)。

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

2
dplehati

これはKitKatで発生し、Android dev http://developer.Android.com/guide/webapps/migrating.html#TouchCancel に従ってtouchcancelを処理することで解決されます。

古いAndroidバージョンでは、問題はAndroid preventdefaultがtouchstartイベントに適用されていない場合、タッチイベントをwebviewに渡さないことにより発生します。これは、何百万ものAndroidデバイス。 https://github.com/TNT-RoX/Android-swipe-shim

1
tnt-rox

このような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;
   }
});
1
Petr Peller

ここで、スクロールを有効にしておく解決策:

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