Gest dotyku występuje, gdy użytkownik zbliży co najmniej 1 palec na ekranie dotykowym, a aplikacja zinterpretuje ten wzorzec dotknięć jako gest. OK Wykrywanie gestów dzieli się na 2 fazy:
- Zbieram dane zdarzeń dotknięcia.
- Interpretacja danych w celu określenia, czy spełniają one kryteria gestów obsługiwanych przez aplikację.
Zajęcia na AndroidzieX
Przykłady w tym dokumencie wykorzystują
GestureDetectorCompat
oraz
MotionEventCompat
zajęcia. Zajęcia te są dostępne na urządzeniach z Androidem X
Biblioteka. Tam, gdzie to możliwe, używaj klas AndroidaX, aby zapewnić zgodność z
starszych urządzeń.
MotionEventCompat
nie zastępuje
MotionEvent
zajęcia. Udostępnia on statyczne metody narzędzia, którym przekazujesz
MotionEvent
obiekt, aby otrzymać powiązane z nim działanie
.
Zbieranie danych
Gdy użytkownik nałożyć na ekran co najmniej 1 palcem,
oddzwanianie
onTouchEvent()
w widoku, w którym są rejestrowane zdarzenia dotknięcia. Dla każdej sekwencji dotyku
zdarzeń takich jak pozycja, ciśnienie, wielkość i dodawanie
palec, który jest rozpoznawany jako gest, onTouchEvent()
to
kilka razy uruchamiany.
Gest uruchamia się, gdy użytkownik po raz pierwszy dotyka ekranu, i jest kontynuowany
system śledzi położenie palca użytkownika i kończy się
nagrywanie ostatniego zdarzenia polegającego na opuszczeniu ekranu ostatniego palca użytkownika.
W trakcie tej interakcji reklama MotionEvent
dostarczała wiadomości
onTouchEvent()
podaje szczegóły każdej interakcji. Twoja aplikacja
może użyć danych dostarczonych przez MotionEvent
do określenia, czy
gestami, na których jest dla niego ważny gest.
Rejestrowanie zdarzeń dotknięcia w ramach aktywności lub widoku
Aby przechwytywać zdarzenia dotyku w Activity
lub
View
, zastąp wywołanie zwrotne onTouchEvent()
.
W poniższym fragmencie kodu
getAction()
aby wyodrębnić z parametru event
działanie wykonywane przez użytkownika.
Dzięki temu otrzymujesz nieprzetworzone dane, dzięki którym możesz określić, czy gest jest dla Ciebie ważny
na temat.
Kotlin
class MainActivity : Activity() { ... // This example shows an Activity. You can use the same approach if you are // subclassing a View. override fun onTouchEvent(event: MotionEvent): Boolean { return when (event.action) { MotionEvent.ACTION_DOWN -> { Log.d(DEBUG_TAG, "Action was DOWN") true } MotionEvent.ACTION_MOVE -> { Log.d(DEBUG_TAG, "Action was MOVE") true } MotionEvent.ACTION_UP -> { Log.d(DEBUG_TAG, "Action was UP") true } MotionEvent.ACTION_CANCEL -> { Log.d(DEBUG_TAG, "Action was CANCEL") true } MotionEvent.ACTION_OUTSIDE -> { Log.d(DEBUG_TAG, "Movement occurred outside bounds of current screen element") true } else -> super.onTouchEvent(event) } } }
Java
public class MainActivity extends Activity { ... // This example shows an Activity. You can use the same approach if you are // subclassing a View. @Override public boolean onTouchEvent(MotionEvent event){ switch(event.getAction()) { case (MotionEvent.ACTION_DOWN) : Log.d(DEBUG_TAG,"Action was DOWN"); return true; case (MotionEvent.ACTION_MOVE) : Log.d(DEBUG_TAG,"Action was MOVE"); return true; case (MotionEvent.ACTION_UP) : Log.d(DEBUG_TAG,"Action was UP"); return true; case (MotionEvent.ACTION_CANCEL) : Log.d(DEBUG_TAG,"Action was CANCEL"); return true; case (MotionEvent.ACTION_OUTSIDE) : Log.d(DEBUG_TAG,"Movement occurred outside bounds of current screen element"); return true; default : return super.onTouchEvent(event); } }
Gdy użytkownik klika ten kod, tworzy on w Logcat komunikat podobny do tego: dotknięcia i przytrzymuje i przeciąga:
GESTURES D Action was DOWN GESTURES D Action was UP GESTURES D Action was MOVE
Możesz też samodzielnie przetwarzać zdarzenia, aby:
określają, czy jest to gest, który musisz wykonać. Jeśli jednak
aplikacja używa typowych gestów, takich jak dwukrotne kliknięcie, dotyk trzymać, rzucać i tak dalej,
możesz skorzystać z
GestureDetector
zajęcia. GestureDetector
ułatwia wykrywanie częstych problemów
bez konieczności samodzielnego przetwarzania poszczególnych zdarzeń dotknięcia. To jest
omówiono dokładnie w sekcji Wykrywanie gestów.
Rejestruj zdarzenia dotknięcia w jednym widoku
Zamiast onTouchEvent()
możesz dołączyć plik
View.OnTouchListener
do dowolnego obiektu View
za pomocą funkcji
setOnTouchListener()
. Dzięki temu można nasłuchiwać zdarzeń dotknięcia bez podklasyfikowania
istniejące View
, jak w tym przykładzie:
Kotlin
findViewById<View>(R.id.my_view).setOnTouchListener { v, event -> // Respond to touch events. true }
Java
View myView = findViewById(R.id.my_view); myView.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { // Respond to touch events. return true; } });
Uważaj na utworzenie detektora, który zwróci wartość false
dla
ACTION_DOWN
.
Jeśli to zrobisz, odbiornik nie zostanie wywołany
ACTION_MOVE
i
Sekwencja ACTION_UP
zdarzeń. Dzieje się tak, ponieważ ACTION_DOWN
jest punktem wyjścia dla wszystkich
dotknięcia.
Jeśli tworzysz widok niestandardowy, możesz zastąpić widok
onTouchEvent()
, jak opisano wcześniej.
Wykrywanie gestów
Android udostępnia klasę GestureDetector
do wykrywania typowych treści
gestami. Obsługuje ona m.in. takie gesty,
onDown()
,
onLongPress()
,
oraz
onFling()
Możesz używać GestureDetector
w połączeniu z
Metoda onTouchEvent()
opisana wcześniej.
Wykryj wszystkie obsługiwane gesty
Podczas tworzenia instancji obiektu GestureDetectorCompat
jedna z metod
to klasa implementująca
GestureDetector.OnGestureListener
za pomocą prostego interfejsu online. GestureDetector.OnGestureListener
powiadamia użytkowników, gdy
konkretne zdarzenie dotknięcia. Aby umożliwić wydawcom
GestureDetector
do odbierania zdarzeń, zastąpić widok lub
metody onTouchEvent()
aktywności i przekazywać wszystkie zaobserwowane zdarzenia
do instancji wzorca.
W tym fragmencie kodu zwracana jest wartość true
z parametru
poszczególne metody on<TouchEvent>
wskazują, że
obsługiwane jest zdarzenie dotknięcia. Wartość zwrotna równa false
pomija zdarzenia
na stosie widoku aż do kliknięcia.
Jeśli uruchomisz ten fragment kodu w aplikacji testowej, możesz sprawdzić,
są wywoływane podczas interakcji z ekranem dotykowym oraz
zawartość MotionEvent
dotyczy każdego zdarzenia dotknięcia. Zobaczysz wówczas
ile danych jest generowanych na potrzeby prostych interakcji.
Kotlin
private const val DEBUG_TAG = "Gestures" class MainActivity : Activity(), GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener { private lateinit var mDetector: GestureDetectorCompat // Called when the activity is first created. public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Instantiate the gesture detector with the // application context and an implementation of // GestureDetector.OnGestureListener. mDetector = GestureDetectorCompat(this, this) // Set the gesture detector as the double-tap // listener. mDetector.setOnDoubleTapListener(this) } override fun onTouchEvent(event: MotionEvent): Boolean { return if (mDetector.onTouchEvent(event)) { true } else { super.onTouchEvent(event) } } override fun onDown(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onDown: $event") return true } override fun onFling( event1: MotionEvent, event2: MotionEvent, velocityX: Float, velocityY: Float ): Boolean { Log.d(DEBUG_TAG, "onFling: $event1 $event2") return true } override fun onLongPress(event: MotionEvent) { Log.d(DEBUG_TAG, "onLongPress: $event") } override fun onScroll( event1: MotionEvent, event2: MotionEvent, distanceX: Float, distanceY: Float ): Boolean { Log.d(DEBUG_TAG, "onScroll: $event1 $event2") return true } override fun onShowPress(event: MotionEvent) { Log.d(DEBUG_TAG, "onShowPress: $event") } override fun onSingleTapUp(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onSingleTapUp: $event") return true } override fun onDoubleTap(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onDoubleTap: $event") return true } override fun onDoubleTapEvent(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onDoubleTapEvent: $event") return true } override fun onSingleTapConfirmed(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onSingleTapConfirmed: $event") return true } }
Java
public class MainActivity extends Activity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener{ private static final String DEBUG_TAG = "Gestures"; private GestureDetectorCompat mDetector; // Called when the activity is first created. @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Instantiate the gesture detector with the // application context and an implementation of // GestureDetector.OnGestureListener. mDetector = new GestureDetectorCompat(this,this); // Set the gesture detector as the double-tap // listener. mDetector.setOnDoubleTapListener(this); } @Override public boolean onTouchEvent(MotionEvent event){ if (this.mDetector.onTouchEvent(event)) { return true; } return super.onTouchEvent(event); } @Override public boolean onDown(MotionEvent event) { Log.d(DEBUG_TAG,"onDown: " + event.toString()); return true; } @Override public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString()); return true; } @Override public void onLongPress(MotionEvent event) { Log.d(DEBUG_TAG, "onLongPress: " + event.toString()); } @Override public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX, float distanceY) { Log.d(DEBUG_TAG, "onScroll: " + event1.toString() + event2.toString()); return true; } @Override public void onShowPress(MotionEvent event) { Log.d(DEBUG_TAG, "onShowPress: " + event.toString()); } @Override public boolean onSingleTapUp(MotionEvent event) { Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString()); return true; } @Override public boolean onDoubleTap(MotionEvent event) { Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString()); return true; } @Override public boolean onDoubleTapEvent(MotionEvent event) { Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString()); return true; } @Override public boolean onSingleTapConfirmed(MotionEvent event) { Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString()); return true; } }
Wykrywanie zestawu obsługiwanych gestów
Jeśli chcesz przetworzyć tylko kilka gestów, możesz rozszerzyć
GestureDetector.SimpleOnGestureListener
zamiast implementować GestureDetector.OnGestureListener
.
za pomocą prostego interfejsu online.
GestureDetector.SimpleOnGestureListener
udostępnia
dla wszystkich
on<TouchEvent>
metod, zwracając
false
. Umożliwia to zastąpienie tylko metod
na których Ci zależy. Na przykład ten fragment kodu tworzy klasę, która rozszerza
GestureDetector.SimpleOnGestureListener
i zastąpienia
onFling()
i onDown()
.
Niezależnie od tego, czy korzystasz z usługi GestureDetector.OnGestureListener
czy
GestureDetector.SimpleOnGestureListener
, najlepiej jest
zaimplementuj metodę onDown()
, która zwraca true
. Ten
jest, że wszystkie gesty zaczynają się od komunikatu onDown()
. Jeśli
zwróć false
od: onDown()
, jako
GestureDetector.SimpleOnGestureListener
domyślnie
zakłada, że chcesz zignorować resztę gestu, a inne metody
GestureDetector.OnGestureListener
nie są wywoływane. Może to spowodować
nieoczekiwane problemy z aplikacją. Zwróć tylko false
od
onDown()
, jeśli naprawdę chcesz zignorować cały gest.
Kotlin
private const val DEBUG_TAG = "Gestures" class MainActivity : Activity() { private lateinit var mDetector: GestureDetectorCompat public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mDetector = GestureDetectorCompat(this, MyGestureListener()) } override fun onTouchEvent(event: MotionEvent): Boolean { mDetector.onTouchEvent(event) return super.onTouchEvent(event) } private class MyGestureListener : GestureDetector.SimpleOnGestureListener() { override fun onDown(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onDown: $event") return true } override fun onFling( event1: MotionEvent, event2: MotionEvent, velocityX: Float, velocityY: Float ): Boolean { Log.d(DEBUG_TAG, "onFling: $event1 $event2") return true } } }
Java
public class MainActivity extends Activity { private GestureDetectorCompat mDetector; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDetector = new GestureDetectorCompat(this, new MyGestureListener()); } @Override public boolean onTouchEvent(MotionEvent event){ if (this.mDetector.onTouchEvent(event)) { return true; } return super.onTouchEvent(event); } class MyGestureListener extends GestureDetector.SimpleOnGestureListener { private static final String DEBUG_TAG = "Gestures"; @Override public boolean onDown(MotionEvent event) { Log.d(DEBUG_TAG,"onDown: " + event.toString()); return true; } @Override public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString()); return true; } } }