Gestur multi-sentuh adalah saat beberapa pointer (jari) mengetuk layar secara bersamaan. Dokumen ini menjelaskan cara mendeteksi gestur yang melibatkan beberapa pointer.
Melacak beberapa pointer
Saat beberapa pointer mengetuk layar secara bersamaan, sistem akan menghasilkan peristiwa sentuh berikut:
ACTION_DOWN
: dikirim saat pointer pertama mengetuk layar. Langkah ini akan memulai gestur. Data pointer untuk pointer ini selalu berada di indeks0
dalamMotionEvent
.ACTION_POINTER_DOWN
: dikirim saat pointer tambahan memasuki layar setelah yang pertama. Anda bisa mendapatkan indeks pointer yang baru saja turun menggunakangetActionIndex()
.ACTION_MOVE
: dikirim saat perubahan terjadi dalam gestur, yang melibatkan sejumlah pointer.ACTION_POINTER_UP
: dikirim saat pointer non-primer naik. Anda bisa mendapatkan indeks pointer yang baru saja naik menggunakangetActionIndex()
.ACTION_UP
: dikirim saat pointer terakhir meninggalkan layar.ACTION_CANCEL
: menunjukkan bahwa seluruh gestur, termasuk semua pointer, dibatalkan.
Gestur awal dan akhir
Gestur adalah serangkaian peristiwa yang dimulai dengan peristiwa ACTION_DOWN
dan diakhiri dengan peristiwa ACTION_UP
atau
ACTION_CANCEL
. Hanya ada satu gestur yang aktif dalam satu waktu. Tindakan
BAWAH, GERAK, ATAS, dan BATAL berlaku untuk seluruh gestur. Misalnya, peristiwa dengan ACTION_MOVE
dapat menunjukkan gerakan untuk semua pointer
ke bawah pada saat itu.
Melacak pointer
Gunakan indeks dan ID pointer untuk melacak setiap posisi
pointer dalam MotionEvent
.
- Indeks:
MotionEvent
menyimpan informasi pointer dalam array. Indeks pointer adalah posisinya dalam array ini. Sebagian besar metodeMotionEvent
menggunakan indeks pointer sebagai parameter, bukan ID pointer. - ID: setiap pointer juga memiliki pemetaan ID yang tetap ada di seluruh peristiwa sentuh untuk memungkinkan pelacakan setiap pointer di seluruh gestur.
Setiap pointer muncul dalam peristiwa gerakan dalam urutan yang tidak ditentukan. Dengan demikian,
indeks pointer dapat berubah dari satu peristiwa ke peristiwa berikutnya, tetapi ID pointer
dari pointer dipastikan tetap konstan selama pointer tetap
aktif. Gunakan metode
getPointerId()
untuk mendapatkan ID pointer guna melacak pointer di semua peristiwa
gerakan berikutnya dalam gestur. Kemudian, untuk peristiwa gerakan berturut-turut, gunakan metode
findPointerIndex()
untuk mendapatkan indeks pointer untuk ID pointer yang diberikan dalam peristiwa gerakan tersebut.
Contoh:
Kotlin
private var mActivePointerId: Int = 0 override fun onTouchEvent(event: MotionEvent): Boolean { ... // Get the pointer ID. mActivePointerId = event.getPointerId(0) // ... Many touch events later... // Use the pointer ID to find the index of the active pointer // and fetch its position. val (x: Float, y: Float) = event.findPointerIndex(mActivePointerId).let { pointerIndex -> // Get the pointer's current position. event.getX(pointerIndex) to event.getY(pointerIndex) } ... }
Java
private int mActivePointerId; public boolean onTouchEvent(MotionEvent event) { ... // Get the pointer ID. mActivePointerId = event.getPointerId(0); // ... Many touch events later... // Use the pointer ID to find the index of the active pointer // and fetch its position. int pointerIndex = event.findPointerIndex(mActivePointerId); // Get the pointer's current position. float x = event.getX(pointerIndex); float y = event.getY(pointerIndex); ... }
Untuk mendukung beberapa pointer sentuh, Anda dapat meng-cache semua pointer aktif dengan
ID-nya pada waktu peristiwa ACTION_POINTER_DOWN
dan
ACTION_DOWN
masing-masing. Hapus pointer dari cache Anda pada
peristiwa ACTION_POINTER_UP
dan ACTION_UP
. Anda mungkin
menemukan ID yang di-cache ini berguna untuk menangani peristiwa tindakan lainnya dengan benar. Misalnya, saat memproses peristiwa ACTION_MOVE
, temukan indeks untuk
setiap ID pointer aktif yang di-cache, ambil koordinat pointer menggunakan
fungsi
getX()
dan
getY()
, lalu bandingkan koordinat ini dengan koordinat yang di-cache untuk
menemukan pointer mana yang dipindahkan.
Gunakan fungsi getActionIndex()
dengan
hanya peristiwa ACTION_POINTER_UP
dan ACTION_POINTER_DOWN
. Jangan gunakan fungsi ini dengan peristiwa ACTION_MOVE
, karena fungsi ini selalu menampilkan 0
.
Mengambil tindakan MotionEvent
Gunakan
metode
getActionMasked()
atau versi kompatibilitas
MotionEventCompat.getActionMasked()
untuk mengambil tindakan MotionEvent
. Tidak seperti metode
getAction()
sebelumnya, getActionMasked()
dirancang untuk berfungsi dengan beberapa
pointer. Fungsi ini menampilkan tindakan tanpa indeks pointer. Untuk tindakan dengan
indeks pointer yang valid, gunakan getActionIndex()
untuk menampilkan indeks
pointer yang terkait dengan tindakan seperti yang ditunjukkan dalam cuplikan berikut:
Kotlin
val (xPos: Int, yPos: Int) = MotionEventCompat.getActionMasked(event).let { action -> Log.d(DEBUG_TAG, "The action is ${actionToString(action)}") // Get the index of the pointer associated with the action. MotionEventCompat.getActionIndex(event).let { index -> // The coordinates of the current screen contact, relative to // the responding View or Activity. MotionEventCompat.getX(event, index).toInt() to MotionEventCompat.getY(event, index).toInt() } } if (event.pointerCount > 1) { Log.d(DEBUG_TAG, "Multitouch event") } else { // Single touch event. Log.d(DEBUG_TAG, "Single touch event") } ... // Given an action int, returns a string description. fun actionToString(action: Int): String { return when (action) { MotionEvent.ACTION_DOWN -> "Down" MotionEvent.ACTION_MOVE -> "Move" MotionEvent.ACTION_POINTER_DOWN -> "Pointer Down" MotionEvent.ACTION_UP -> "Up" MotionEvent.ACTION_POINTER_UP -> "Pointer Up" MotionEvent.ACTION_OUTSIDE -> "Outside" MotionEvent.ACTION_CANCEL -> "Cancel" else -> "" } }
Java
int action = MotionEventCompat.getActionMasked(event); // Get the index of the pointer associated with the action. int index = MotionEventCompat.getActionIndex(event); int xPos = -1; int yPos = -1; Log.d(DEBUG_TAG,"The action is " + actionToString(action)); if (event.getPointerCount() > 1) { Log.d(DEBUG_TAG,"Multitouch event"); // The coordinates of the current screen contact, relative to // the responding View or Activity. xPos = (int)MotionEventCompat.getX(event, index); yPos = (int)MotionEventCompat.getY(event, index); } else { // Single touch event. Log.d(DEBUG_TAG,"Single touch event"); xPos = (int)MotionEventCompat.getX(event, index); yPos = (int)MotionEventCompat.getY(event, index); } ... // Given an action int, returns a string description public static String actionToString(int action) { switch (action) { case MotionEvent.ACTION_DOWN: return "Down"; case MotionEvent.ACTION_MOVE: return "Move"; case MotionEvent.ACTION_POINTER_DOWN: return "Pointer Down"; case MotionEvent.ACTION_UP: return "Up"; case MotionEvent.ACTION_POINTER_UP: return "Pointer Up"; case MotionEvent.ACTION_OUTSIDE: return "Outside"; case MotionEvent.ACTION_CANCEL: return "Cancel"; } return ""; }
Referensi lainnya
Untuk informasi selengkapnya terkait peristiwa input, lihat referensi berikut:
- Ringkasan peristiwa input
- Ringkasan sensor
- Membuat tampilan kustom menjadi interaktif
- Menarik dan menskalakan