Android-Browser verzaubert Ereignisse für zwei aufeinander folgende Taps

9

Ich versuche JavaScript und jQuery zu verwenden, um Berührungsereignisse zu erfassen. Aber ich sehe ein sehr seltsames Verhalten im Webbrowser unter Android 2.3.2: Immer wenn ich auf den Bildschirm tippe und dann schnell irgendwo anders auf dem Bildschirm tippe, der Browser:

  • zeigt momentan einen orangefarbenen Rahmen und hebt den gesamten Bildschirm hervor, und
  • sendet mir die falschen Ereignisse.

Der orange Rand scheint nur ein verwandtes Symptom des gleichen zugrunde liegenden Problems zu sein, also mache ich mir keine Sorgen darüber - es ist tatsächlich praktisch, um zu wissen, wann der Browser Dinge vermasselt. Was ich wirklich wissen möchte, ist wie kann ich immer die richtigen Berührungsereignisse für zwei schnelle Antippen erhalten? Ich glaube, wenn das Problem gelöst ist, wird der orange Rand ebenfalls verschwinden.

>

Was folgt, sind all die schmerzhaften Details, die ich bisher erarbeitet habe.

Hier ist eine Seite, die das Problem zeigt und eine Menge diagnostischer Informationen über die Details und Details anzeigt Zeitpunkt jedes empfangenen Ereignisses. Sie werden sicher die orangefarbenen Flash- / Bad-Ereignisse erhalten, wenn Sie auf das blaue Rechteck tippen und dann schnell auf das schwarze Rechteck tippen.

Mein jQuery-Code ist ziemlich Standard. Die Implementierung von log ist nicht wichtig. Das Problem ist, dass der Browser es nicht aufruft, wenn es sollte.

%Vor%

Weitere Details zu den eingangs beschriebenen Phänomenen:

Orange Rahmen und Hervorhebung: Dies ist der gleiche orange Rahmen und hebt hervor, dass der Browser einen Hyperlink umrahmt, wenn Sie darauf klicken. Aber es gibt keine Hyperlinks auf der Seite, und der Browser zeichnet diesen orangefarbenen Rahmen um den gesamten Bildschirm herum - oder genauer gesagt, um den äußeren <div id="battle"> , an den ich Ereignisse über jQuery anhänge.

Falsche Ereignisse: In meinem touchstart Ereignishandler rufe ich event.preventDefault() an, um dem Browser zu sagen, dass er nicht scrollt, Mausereignisse usw. nicht synthetisiert. Deshalb erwarte ich das Erhalten Sie nur touchstart und touchend Ereignisse. Und ich tue es, beim ersten Tippen. Aber anstatt touchstart / touchend für den zweiten Tipp, erhalte ich eine ganze Anzahl von Kombinationen von Berührungsereignissen, synthetisierten Mausereignissen und gelegentlich touchcancel für das zweite Tippen oder sogar wiederholte Ereignisse für das erste Tippen. Details unten.

Dieses Verhalten tritt auch nur unter ganz bestimmten Umständen auf:

  • Der erste Tipp muss kurz sein (weniger als ~ 200ms).
  • Der zweite Tipp muss schnell kommen (weniger als ~ 450ms nach dem touchstart des ersten Tap).
  • Der zweite Tap muss mindestens 150 Pixel vom ersten Tap entfernt sein (gemessen entlang der Diagonalen von den Koordinaten des touchstart des ersten Tap).
  • Wenn ich meinen Code mit den Hooks mousedown und mouseup entferne, werden die orangefarbenen Rechtecke nicht mehr angezeigt. Die Berührungsereignisse sind jedoch manchmal immer noch verstümmelt.

Soweit ich meine, dass die Ereignisse verstümmelt sind, hier ist, was ich sehe. Wenn ich "1:" schreibe, bedeutet das, dass die Ereignisse für die ersten Tap-Koordinaten sind; "2:" bedeutet die Koordinaten des zweiten Tap. Ich sah die folgenden Muster von Ereignissen (Prozentsätze zeigen an, wie oft jede nach 100 Versuchen auftauchte):

  • (50%) 1: Touchstart 1: Touchend 1: Mausklick 1: Mausklick (kurze Verzögerung) 2: Mausklick 2: Mausklick
  • (35%) 1: Touchstart 1: Touchend 2: Touchstart 1: Mausklick 1: Mausklick 2: Touchend
  • (10%) 1: Touchstart 1: Touchend 2: Touchstart 1: Mausklick 1: Mausklick 2: Touchcancel (kurze Verzögerung) 2: Mausklick 2: Mausklick
  • (3%) 1: Touchstart 1: Touchend 2: Touchstart 2: Touchend (kurze Verzögerung) 1: mousedown 1: mouseup
  • (2%) 1: touchstart 1: touchend 1: mousedown 1: mouseup (und nichts für den zweiten Tap)

Einige Kombinationen von Ereignissen scheinen häufiger zu kommen, je nachdem, wie schnell ich tippe, aber ich habe das Muster noch nicht ganz durchnässt. (Zwei schnelle, scharfe Hähne scheinen eher unter dem zweiten Punkt oben zu erscheinen, während ein schnellerer Ansatz mit weniger Betonung der Knusprigkeit eher der erste Gegenstand ist. Aber ich habe keine spezifischen Timing-Zahlen identifiziert, die dazu führen zu jedem.) In ähnlicher Weise können die oben angegebenen "kurzen Verzögerungen" irgendwo zwischen ~ 150 ms und ~ 400 ms liegen; Ich habe das ganze Muster auch dort nicht rückentwickelt.

Wenn ich mousedown und mouseup nicht hake, ist die Verteilung grob wie folgt:

  • (40%) 1: Touchstart 1: Touchend 2: Touchstart 2: Touchcancel
  • (35%) 1: Touchstart 1: Touchend 2: Touchstart 2: Touchend (das tatsächlich gewünschte Verhalten)
  • (25%) 1: Touchstart 1: touchend (und nichts für den zweiten Tipp)

Wenn ich also die Mausereignisse nicht hake, funktioniert es ein Drittel der Zeit; und wenn ich bereit wäre vorzutäuschen, dass touchcancel dasselbe bedeutet wie touchend , könnte ich das bis zu 75% der Zeit bekommen. Aber das ist immer noch ziemlich sucky.

Alternativen, die ich schon versucht habe:

  • Ich habe versucht, jQuery Mobile vmousedown und vmouseup -Ereignisse , aber sie werden nicht immer für den zweiten Tipp ausgelöst, ich vermute wegen der gleichen zugrunde liegenden Ereignis Seltsamkeit.
  • Ich könnte Berührungsereignisse einfach ganz vergessen und nur die synthetisierten Mausereignisse verwenden, aber es gibt normalerweise eine Verzögerung von etwa einer halben Sekunde zwischen der physischen Berührung und der Lieferung des synthetisierten Mausereignisses, während die Berührungsereignisse unmittelbar sind reaktionsfähiger sein. Ich möchte auch das Scrollen verhindern - das ist für ein Fullscreen-Spiel, und ich möchte lieber nicht, dass der Benutzer versehentlich die Adressleiste in den Blick scrollt und einen Teil des Spiels blockiert - und preventDefault auf touchstart tut. erreicht dies normalerweise (obwohl gelegentlich das zweite Tippen tatsächlich den Bildschirm scrollen kann trotz meiner preventDefault ... ein anderer Grund, den ich dieses ganze Ereignischaos lösen möchte).
  • Ich habe einen Webbrowser eines Drittanbieters ausprobiert ( Dolphin ), aber es hat die gleichen Probleme mit Ereignissen. Ich vermute, es ist wahrscheinlich ein Problem mit der Art und Weise, wie das zugrundeliegende WebView Ereignisse an Skripte liefert.

Kann jemand vorschlagen, wie ich meinen HTML-Code, meine Event-Handler oder irgendetwas anderes ändern kann, um Touch-Ereignisse für zwei aufeinanderfolgende schnelle Antippen zuverlässig zu erhalten?

    
Joe White 18.12.2011, 00:02
quelle

5 Antworten

3

Nachdem ich versucht habe, Multi-Touch-HTML5-Spiele im Android-Browser zu entwickeln (und sie auch in anderen Android-kompatiblen Browsern auszuprobieren), denke ich, dass der Browser von Android 2.x die Berührungseingabe einfach nicht richtig unterstützt. Für den Anfang unterstützt es Multi-Touch nicht, was einige Arten von Spielen unspielbar macht. (Offensichtlich unterstützt das Telefon Multitouch, weil Sie zoomen können usw., aber der Browser nicht.) Dann gibt es viele Probleme mit Latenz, Berührungen ' und so weiter. Ich erinnere mich vage daran, dass ich etwas über die Treiber des Telefons für Touch-Eingaben gelesen habe, die nicht wirklich mit True Multitouch funktionieren (dh es kann entweder Single-Touch- oder Pinch-Zooms erkennen und das wars), aber ich habe keine Hinweise darauf, dass ich zurückkomme ... / p>

Anscheinend behebt Android 4 (Ice Cream Sandwich) es. Sie müssen also vielleicht nur auf Android 4 warten, das sowieso bald veröffentlicht werden sollte, und es erneut versuchen. Darüber hinaus haben Google angekündigt, den Android Browser in Zukunft durch eine mobile Version von Chrome zu ersetzen, sodass hoffentlich zumindest bis dahin unsere Touch-Eingabe-Probleme vorbei sind.

    
AshleysBrain 20.12.2011, 14:01
quelle
1

Das ist eine Theorie: Konnte nicht ausgiebig testen

Laut init Funktion im Quellcode einer Webview , wird die Anweisung setFocusable(true) immer in einer Webansicht aufgerufen während seiner Initialisierung.

Als ich versuchte, die Ansicht nicht mehr fokussierbar zu machen, indem ich setFocusable(false) verwendete, trat der Fehler nicht erneut auf. Es scheint, dass die orange Box nicht erscheint. Ich testete dies auf einem kleinen Samsung-Handy mit OS 2.3.4. Ich bin mir sicher, dass diese orange Box nicht wieder erscheint.

Falls sich herausstellt, dass dies wahr ist, ist es sehr wahrscheinlich, dass wir dies ohne unser eigenes Webview lösen können. Was die Dinge komplizierter macht, ist, wenn Sie die fokussierbare Eigenschaft auf false setzen, löst andere Probleme aus.

Schließlich glaube ich nicht, dass wir diese Eigenschaft von Javascript aus kontrollieren können (oder können wir?). Vielleicht können Sie deklarieren, dass ein bestimmtes Steuerelement oder das gesamte Dokument keine Eingabe oder etwas ähnliches ist? Ich extrapoliere nur so weit, dass dies falsch sein kann.

Bearbeiten: In Bezug auf Ihren Kommentar zu Ihrer Frage Ich habe gerade eine leere Anwendung mit nur einem Webview erstellt, die Ihre URL lädt, nachdem Sie ihre fokussierbare Eigenschaft auf false festgelegt haben. Bitte, wenn Sie mehr Ressourcen haben, um es zu testen, werde ich es für Sie hochladen, um es zu versuchen. Hier ist die Anwendung

    
Sherif elKhatib 20.12.2011 14:11
quelle
0

Haben Sie versucht, die jQuery Mobile-Ereignisse zu verwenden? Die entkoppelten Widgets / Plugins finden Sie hier:

Ссылка

Sie werden wahrscheinlich jquery.mobile.event.js und jquery.mobile.vmouse.js

benötigen

Jetzt können Sie einfach die Ereignisse in jQuery mit dem Tap, Swipe usw. verknüpfen. Oder muss zwischen Anfang und Ende eines Tap unterschieden werden?

    
daan 20.12.2011 14:14
quelle
0

statt alle Ereignisse anzuhängen, indem du versuchst, dies zu versuchen, funktioniert es vielleicht für dich

%Vor%     
pravin 21.12.2011 04:22
quelle
0

Haben Sie versucht, das Ereignis direkt anzuhängen?

%Vor%

(Sorry, wenn der Code wirklich schlampig ist, habe ich der Log-Funktion nicht wirklich viel Aufmerksamkeit geschenkt, aber ich habe kleinere Änderungen vorgenommen, da er bei meinem touchend-Event nicht korrekt als event.touches [0 ] .pageX ist zu diesem Zeitpunkt undefiniert. Auch habe ich es in eine fertige Funktion eingepackt, weil ich nur faul war :-P)

Da dies nur die erste Berührung verfolgt (event.touches [0]), können Sie wahrscheinlich einige Einstellungen vornehmen, um Multi-Touch zu testen, indem Sie das Touch-Array nach unten gehen. Was ich auf meinem Android-Gerät (Lebkuchen) entdeckt habe, ist, dass wenn du zwei Finger gleichzeitig auf dem Bildschirm hast, das Touchend-Ereignis nur ausgelöst wird, wenn die letzte Berührung losgelassen wird; d.h. die zweite Fingerfreigabe.

Wenn ich die mouseup / mouseup Event-Listener angeschlossen habe, dann habe ich genau das Gleiche mit dem ganzen orangefarbenen Highlight-Ding gemacht.

Das Gerät, das ich getestet habe, war ein Samsung Droid Charge mit OTA Gingerbread Update.

    
ayc 23.12.2011 00:43
quelle