Mendeteksi gestur umum

Mencoba cara Compose
Jetpack Compose adalah toolkit UI yang direkomendasikan untuk Android. Pelajari cara menggunakan sentuhan dan input di Compose.

Gestur sentuh terjadi saat pengguna meletakkan satu atau beberapa jari di layar sentuh dan aplikasi Anda menginterpretasikan pola sentuhan ini sebagai gestur. Ada adalah dua fase untuk deteksi gestur:

  1. Mengumpulkan data peristiwa sentuh.
  2. Menafsirkan data untuk menentukan apakah data itu memenuhi kriteria untuk {i>gesture <i}yang didukung aplikasi Anda.

Class AndroidX

Contoh dalam dokumen ini menggunakan GestureDetectorCompat dan MotionEventCompat Google Cloud Platform. Class ini tersedia di AndroidX Library. Gunakan class AndroidX jika memungkinkan untuk menyediakan kompatibilitas dengan perangkat sebelumnya. MotionEventCompat bukan pengganti untuk MotionEvent . Sebaliknya, ia menyediakan metode utilitas statis yang Anda teruskan MotionEvent untuk menerima tindakan yang terkait dengannya peristiwa.

Mengumpulkan data

Ketika pengguna menempatkan satu atau beberapa jari di layar, hal ini memicu telepon balik onTouchEvent() pada tampilan yang menerima peristiwa sentuh. Untuk setiap urutan sentuhan — seperti posisi, tekanan, ukuran, dan penambahan jari—yang diidentifikasi sebagai gestur, onTouchEvent() adalah beberapa kali diaktifkan.

Gestur dimulai ketika pengguna pertama kali menyentuh layar, berlanjut ketika melacak posisi jari atau jari pengguna, dan diakhiri dengan menangkap peristiwa terakhir dari jari terakhir pengguna yang meninggalkan layar. Sepanjang interaksi ini, MotionEvent dikirimkan ke onTouchEvent() memberikan detail setiap interaksi. Aplikasi Anda dapat menggunakan data yang disediakan oleh MotionEvent untuk menentukan apakah {i>gesture <i}yang diinginkan.

Menangkap peristiwa sentuhan untuk Aktivitas atau Tampilan

Untuk mencegat peristiwa sentuh dalam Activity atau View, ganti callback onTouchEvent().

Cuplikan kode berikut menggunakan getAction() untuk mengekstrak tindakan yang dilakukan pengguna dari parameter event. Ini memberi Anda data mentah yang Anda butuhkan untuk menentukan apakah {i>gesture <i}Anda tentang terjadi.

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);
    }
}

Kode ini menghasilkan pesan seperti berikut di Logcat saat pengguna mengetuk, sentuhan & menahan, dan menarik:

GESTURES D   Action was DOWN
GESTURES D   Action was UP
GESTURES D   Action was MOVE

Untuk gestur kustom, Anda dapat melakukan pemrosesan sendiri pada peristiwa ini untuk menentukan apakah mereka mewakili {i>gesture <i}yang perlu Anda tangani. Namun, jika aplikasi menggunakan gestur umum, seperti ketuk dua kali, sentuh & terus, ayunkan, dan sebagainya, Anda dapat memanfaatkan GestureDetector . GestureDetector memudahkan Anda mendeteksi masalah {i>gesture <i}tanpa harus memproses peristiwa sentuh individu itu sendiri. Ini adalah dibahas lebih lanjut di Mendeteksi gestur.

Menangkap peristiwa sentuhan untuk satu tampilan

Sebagai alternatif onTouchEvent(), Anda dapat melampirkan View.OnTouchListener objek ke View menggunakan atribut setOnTouchListener() . Hal ini memungkinkan untuk memproses peristiwa sentuh tanpa membuat subclass View yang ada, seperti yang ditunjukkan dalam contoh berikut:

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;
    }
});

Berhati-hatilah dalam membuat pemroses yang menampilkan false untuk Peristiwa ACTION_DOWN. Jika Anda melakukannya, pemroses tidak akan dipanggil untuk ACTION_MOVE dan ACTION_UP urutan peristiwa. Hal ini karena ACTION_DOWN adalah titik awal untuk semua peristiwa sentuh.

Jika Anda membuat tampilan kustom, Anda dapat mengganti onTouchEvent(), seperti yang dijelaskan sebelumnya.

Mendeteksi gestur

Android menyediakan class GestureDetector untuk mendeteksi {i>gestures.<i} Beberapa {i>gestures <i}yang didukung antara lain onDown(), onLongPress(), dan onFling(). Anda dapat menggunakan GestureDetector bersama dengan Metode onTouchEvent() yang dijelaskan sebelumnya.

Mendeteksi semua gestur yang didukung

Saat Anda membuat instance objek GestureDetectorCompat, salah satu parameter yang diperlukan adalah class yang mengimplementasikan GestureDetector.OnGestureListener dalam antarmuka berbasis web yang sederhana. GestureDetector.OnGestureListener memberi tahu pengguna jika terjadi peristiwa sentuh tertentu. Untuk memungkinkan GestureDetector untuk menerima peristiwa, mengganti tampilan, atau metode onTouchEvent() aktivitas dan meneruskan semua peristiwa yang diamati ke instance detektor.

Dalam cuplikan berikut, nilai hasil true dari metode metode on<TouchEvent> individual menunjukkan bahwa peristiwa sentuh akan ditangani. Nilai hasil false akan meneruskan peristiwa ke bawah melewati tumpukan tampilan sampai sentuhan berhasil ditangani.

Jika Anda menjalankan cuplikan berikut di aplikasi pengujian, Anda dapat mengetahui caranya tindakan akan dipicu ketika Anda berinteraksi dengan layar sentuh dan apa konten MotionEvent adalah untuk setiap peristiwa sentuh. Anda kemudian melihat berapa banyak data yang dihasilkan untuk interaksi sederhana.

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;
    }
}

Mendeteksi subset gestur yang didukung

Jika Anda hanya ingin memproses beberapa {i>gestures, <i} Anda dapat memperluas GestureDetector.SimpleOnGestureListener bukan menerapkan GestureDetector.OnGestureListener dalam antarmuka berbasis web yang sederhana.

GestureDetector.SimpleOnGestureListener menyediakan implementasi untuk semua Metode on<TouchEvent> dengan menampilkan false untuk semuanya. Ini memungkinkan Anda mengganti hanya metode yang yang penting bagi Anda. Misalnya, cuplikan kode berikut membuat class yang memperluas GestureDetector.SimpleOnGestureListener dan penggantian onFling() dan onDown().

Baik Anda menggunakan GestureDetector.OnGestureListener atau GestureDetector.SimpleOnGestureListener, sebaiknya implementasikan metode onDown() yang menampilkan true. Ini karena semua gestur dimulai dengan pesan onDown(). Jika Anda tampilkan false dari onDown(), sebagai GestureDetector.SimpleOnGestureListener melakukannya secara default, sistem mengasumsikan Anda ingin mengabaikan sisa {i>gesture <i}dan metode lainnya GestureDetector.OnGestureListener tidak dipanggil. Hal ini dapat menyebabkan masalah tak terduga di aplikasi Anda. Hanya kembalikan false dari onDown() jika Anda benar-benar ingin mengabaikan seluruh gestur.

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;
        }
    }
}

Referensi lainnya