Tutorial ini menjelaskan cara melacak gerakan dalam peristiwa sentuhan.
Fitur baru
onTouchEvent()
dipicu dengan
Peristiwa ACTION_MOVE
setiap kali posisi, tekanan, atau ukuran kontak sentuh saat ini berubah. Sebagai
yang dijelaskan dalam Mendeteksi gestur umum, semuanya
peristiwa ini dicatat dalam
Parameter MotionEvent
dari
onTouchEvent()
.
Karena sentuhan berbasis jari tidak selalu menjadi bentuk interaksi yang paling tepat, mendeteksi peristiwa sentuh sering kali lebih didasarkan pada gerakan daripada kontak sederhana. Untuk membantu aplikasi membedakan antara gestur berbasis gerakan (seperti geser) dan {i>gesture <i}non-gerakan (seperti satu ketukan), Android menyertakan gagasan touch slop. Touch slop mengacu pada jarak dalam piksel yang dapat disentuh pengguna berjalan sebelum {i>gesture <i}diinterpretasikan sebagai {i>gesture <i}berbasis gerakan. Untuk selengkapnya informasi tentang topik ini, lihat Mengelola peristiwa sentuh dalam ViewGroup.
Ada beberapa cara untuk melacak gerakan dalam {i>gesture<i}, tergantung pada kebutuhan aplikasi Anda. Berikut ini contohnya:
- Posisi awal dan akhir pointer, seperti memindahkan pointer di layar objek dari titik A ke titik B.
- Arah pointer bergerak, seperti yang ditentukan oleh X dan Y pada koordinat tertentu.
- Histori. Anda dapat menemukan ukuran histori gestur dengan memanggil
MotionEvent
metodegetHistorySize()
. Anda kemudian bisa mendapatkan posisi, ukuran, waktu, dan tekanan dari masing-masing peristiwa bersejarah dengan menggunakangetHistorical<Value>
metode. Histori berguna saat merender jejak jari pengguna, seperti seperti untuk gambar sentuh. Lihat referensiMotionEvent
untuk mengetahui detailnya. - Kecepatan pointer saat bergerak di layar sentuh.
Lihat referensi terkait berikut:
Melacak kecepatan
Anda dapat memiliki gestur berbasis gerakan yang didasarkan pada jarak atau arah
perjalanan {i>pointer<i}. Namun, kecepatan sering kali menjadi
faktor penentu dalam pelacakan
karakteristik {i>gesture <i}atau
menentukan apakah {i>gesture <i}itu terjadi. Untuk membuat
penghitungan kecepatan lebih mudah, Android menyediakan
Class VelocityTracker
.
VelocityTracker
membantu Anda melacak kecepatan peristiwa sentuh. Hal ini berguna
untuk {i>gesture <i}di mana kecepatan menjadi bagian dari kriteria {i>gesture, <i}
ayunkan jari.
Berikut adalah contoh yang menggambarkan tujuan metode dalam
API VelocityTracker
:
Kotlin
private const val DEBUG_TAG = "Velocity" class MainActivity : Activity() { private var mVelocityTracker: VelocityTracker? = null override fun onTouchEvent(event: MotionEvent): Boolean { when (event.actionMasked) { MotionEvent.ACTION_DOWN -> { // Reset the velocity tracker back to its initial state. mVelocityTracker?.clear() // If necessary, retrieve a new VelocityTracker object to watch // the velocity of a motion. mVelocityTracker = mVelocityTracker ?: VelocityTracker.obtain() // Add a user's movement to the tracker. mVelocityTracker?.addMovement(event) } MotionEvent.ACTION_MOVE -> { mVelocityTracker?.apply { val pointerId: Int = event.getPointerId(event.actionIndex) addMovement(event) // When you want to determine the velocity, call // computeCurrentVelocity(). Then, call getXVelocity() and // getYVelocity() to retrieve the velocity for each pointer // ID. computeCurrentVelocity(1000) // Log velocity of pixels per second. It's best practice to // use VelocityTrackerCompat where possible. Log.d("", "X velocity: ${getXVelocity(pointerId)}") Log.d("", "Y velocity: ${getYVelocity(pointerId)}") } } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { // Return a VelocityTracker object back to be re-used by others. mVelocityTracker?.recycle() mVelocityTracker = null } } return true } }
Java
public class MainActivity extends Activity { private static final String DEBUG_TAG = "Velocity"; ... private VelocityTracker mVelocityTracker = null; @Override public boolean onTouchEvent(MotionEvent event) { int index = event.getActionIndex(); int action = event.getActionMasked(); int pointerId = event.getPointerId(index); switch(action) { case MotionEvent.ACTION_DOWN: if(mVelocityTracker == null) { // Retrieve a new VelocityTracker object to watch the // velocity of a motion. mVelocityTracker = VelocityTracker.obtain(); } else { // Reset the velocity tracker back to its initial state. mVelocityTracker.clear(); } // Add a user's movement to the tracker. mVelocityTracker.addMovement(event); break; case MotionEvent.ACTION_MOVE: mVelocityTracker.addMovement(event); // When you want to determine the velocity, call // computeCurrentVelocity(). Then call getXVelocity() and // getYVelocity() to retrieve the velocity for each pointer ID. mVelocityTracker.computeCurrentVelocity(1000); // Log velocity of pixels per second. It's best practice to use // VelocityTrackerCompat where possible. Log.d("", "X velocity: " + mVelocityTracker.getXVelocity(pointerId)); Log.d("", "Y velocity: " + mVelocityTracker.getYVelocity(pointerId)); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // Return a VelocityTracker object back to be re-used by others. mVelocityTracker.recycle(); break; } return true; } }
Menggunakan rekaman pointer
Beberapa aplikasi, seperti game serta klien desktop jarak jauh dan virtualisasi, mendapatkan manfaat mendapatkan kontrol atas kursor {i>mouse<i}. Perekaman kursor adalah fitur tersedia di Android 8.0 (API level 26) dan yang lebih tinggi yang menyediakan kontrol ini dengan yang mengirimkan semua peristiwa mouse ke tampilan terfokus dalam aplikasi Anda.
Meminta rekaman pointer
Tampilan di aplikasi Anda bisa meminta rekaman pointer hanya jika hierarki tampilan yang
berisi elemen yang memiliki fokus. Karena alasan ini, minta rekaman pointer saat ada
tindakan pengguna tertentu pada tampilan, seperti selama
onClick()
peristiwa atau dalam
onWindowFocusChanged()
pengendali peristiwa
aktivitas Anda.
Untuk meminta rekaman pointer, panggil metode
requestPointerCapture()
pada tampilan. Contoh kode berikut menunjukkan cara meminta pointer
rekam saat pengguna mengklik tampilan:
Kotlin
fun onClick(view: View) { view.requestPointerCapture() }
Java
@Override public void onClick(View view) { view.requestPointerCapture(); }
Setelah permintaan untuk merekam pointer berhasil, Android akan memanggil
onPointerCaptureChange(true)
Sistem mengirimkan peristiwa mouse ke tampilan yang difokuskan dalam aplikasi Anda selama
dalam hierarki tampilan yang sama dengan tampilan yang meminta penangkapan. Yang lain
aplikasi berhenti menerima peristiwa mouse hingga rekaman dirilis, termasuk
ACTION_OUTSIDE
peristiwa. Android mengirim peristiwa pointer dari sumber selain mouse sebagai
normal, tetapi kursor mouse tidak lagi terlihat.
Menangani peristiwa pointer yang direkam
Setelah tampilan berhasil memperoleh rekaman pointer, Android akan mengirimkan peristiwa mouse. Tampilan terfokus dapat menangani peristiwa dengan melakukan salah satu tugas berikut:
- Jika Anda menggunakan tampilan kustom, ganti
onCapturedPointerEvent(MotionEvent)
- Jika tidak, daftarkan
OnCapturedPointerListener
Contoh kode berikut menunjukkan cara mengimplementasikan
onCapturedPointerEvent(MotionEvent)
:
Kotlin
override fun onCapturedPointerEvent(motionEvent: MotionEvent): Boolean { // Get the coordinates required by your app. val verticalOffset: Float = motionEvent.y // Use the coordinates to update your view and return true if the event is // successfully processed. return true }
Java
@Override public boolean onCapturedPointerEvent(MotionEvent motionEvent) { // Get the coordinates required by your app. float verticalOffset = motionEvent.getY(); // Use the coordinates to update your view and return true if the event is // successfully processed. return true; }
Contoh kode berikut menunjukkan cara mendaftarkan
OnCapturedPointerListener
:
Kotlin
myView.setOnCapturedPointerListener { view, motionEvent -> // Get the coordinates required by your app. val horizontalOffset: Float = motionEvent.x // Use the coordinates to update your view and return true if the event is // successfully processed. true }
Java
myView.setOnCapturedPointerListener(new View.OnCapturedPointerListener() { @Override public boolean onCapturedPointer (View view, MotionEvent motionEvent) { // Get the coordinates required by your app. float horizontalOffset = motionEvent.getX(); // Use the coordinates to update your view and return true if the event is // successfully processed. return true; } });
Baik Anda menggunakan tampilan kustom maupun mendaftarkan pemroses, tampilan Anda akan menerima
MotionEvent
dengan koordinat pointer yang menentukan gerakan relatif seperti X
atau Y, mirip dengan koordinat yang
dikirim oleh perangkat trackball. Anda dapat
mengambil koordinat dengan menggunakan
getX()
dan
getY()
.
Merilis rekaman pointer
Tampilan di aplikasi Anda dapat merilis rekaman pointer dengan memanggil
releasePointerCapture()
,
seperti yang ditunjukkan dalam contoh kode berikut:
Kotlin
override fun onClick(view: View) { view.releasePointerCapture() }
Java
@Override public void onClick(View view) { view.releasePointerCapture(); }
Sistem dapat mengambil rekaman dari tampilan tanpa Anda secara eksplisit
memanggil releasePointerCapture()
, umumnya karena hierarki tampilan
berisi tampilan yang permintaan rekamannya akan kehilangan fokus.