Ringkasan peristiwa masukan

Di Android, ada lebih dari satu cara untuk mencegat peristiwa dari interaksi pengguna dengan aplikasi Anda. Saat mempertimbangkan peristiwa dalam antarmuka pengguna Anda, pendekatannya adalah menangkap peristiwa dari objek Tampilan tertentu yang digunakan pengguna untuk berinteraksi. Kelas View menyediakan sarana untuk melakukannya.

Dalam berbagai kelas View yang akan digunakan untuk menyusun layout, Anda mungkin melihat beberapa metode callback publik yang tampak berguna untuk kejadian UI. Metode ini dipanggil oleh kerangka kerja Android ketika masing-masing tindakan terjadi pada objek itu. Misalnya, jika Tampilan (seperti Tombol) disentuh, metode onTouchEvent() akan dipanggil pada objek itu. Namun, untuk mencegatnya, Anda harus memperluas kelas dan mengganti metodenya. Akan tetapi, memperluas setiap objek Tampilan untuk menangani kejadian seperti itu tidaklah praktis. Karena alasan ini kelas Tampilan juga berisi sekumpulan antarmuka bertumpuk dengan callback yang jauh lebih mudah didefinisikan. Antarmuka ini, yang disebut event listener, merupakan tiket Anda untuk menangkap interaksi pengguna dengan UI.

Walaupun Anda akan lebih sering menggunakan event listener ini untuk interaksi pengguna, mungkin ada saatnya Anda ingin memperluas kelas Tampilan, untuk membuat komponen kustom. Mungkin Anda ingin memperluas kelas Button untuk membuat sesuatu yang lebih menarik. Dalam hal ini, Anda akan dapat mendefinisikan perilaku peristiwa default untuk kelas Anda dengan menggunakan kelas event handler.

Event listener

Event listener merupakan antarmuka di kelas View yang berisi metode callback tunggal. Metode ini akan dipanggil oleh framework Android jika Tampilan yang telah didaftarkan dengan listener dipicu oleh interaksi pengguna dengan item dalam UI.

Yang juga disertakan dalam antarmuka event listener adalah metode callback berikut ini:

onClick()
Dari View.OnClickListener. Ini dipanggil baik saat pengguna menyentuh item (jika dalam mode sentuh), maupun memfokuskan pada item dengan tombol navigasi atau trackball dan menekan tombol "enter" yang sesuai atau menekan trackball.
onLongClick()
Dari View.OnLongClickListener. Ini dipanggil baik saat pengguna menyentuh dan menahan item (jika dalam mode sentuh), maupun memfokuskan pada item dengan tombol navigasi atau trackball dan menekan serta menahan tombol "enter" yang sesuai atau menekan dan menahan trackball (selama satu detik).
onFocusChange()
Dari View.OnFocusChangeListener. Ini dipanggil saat pengguna menyusuri ke atau dari item, dengan menggunakan tombol navigasi atau trackball.
onKey()
Dari View.OnKeyListener. Ini dipanggil saat pengguna memfokuskan pada item dan menekan atau melepas tombol perangkat keras pada perangkat.
onTouch()
Dari View.OnTouchListener. Ini dipanggil saat pengguna melakukan tindakan yang digolongkan sebagai peristiwa sentuh, termasuk penekanan, pelepasan, atau isyarat perpindahan pada layar (dalam batasan item itu).
onCreateContextMenu()
Dari View.OnCreateContextMenuListener. Ini dipanggil saat Menu Konteks sedang dibuat (akibat "klik lama" terus-menerus). Lihat diskusi tentang menu konteks di panduan developer Menu.

Metode ini satu-satunya yang menempati antarmukanya masing-masing. Untuk mendefinisikan salah satu metode ini dan menangani peristiwa Anda, implementasikan antarmuka bertumpuk dalam Aktivitas Anda atau definisikan sebagai kelas anonim. Kemudian, teruskan satu instance implementasi Anda pada metode View.set...Listener() masing-masing. (Misalnya, panggil setOnClickListener() dan teruskan implementasi OnClickListener Anda.)

Contoh di bawah menunjukkan cara mendaftarkan on-click listener untuk Button.

Kotlin

protected void onCreate(savedValues: Bundle) {
    ...
    val button: Button = findViewById(R.id.corky)
    // Register the onClick listener with the implementation above
    button.setOnClickListener { view ->
        // do something when the button is clicked
    }
    ...
}

Java

// Create an anonymous implementation of OnClickListener
private OnClickListener corkyListener = new OnClickListener() {
    public void onClick(View v) {
      // do something when the button is clicked
    }
};

protected void onCreate(Bundle savedValues) {
    ...
    // Capture our button from layout
    Button button = (Button)findViewById(R.id.corky);
    // Register the onClick listener with the implementation above
    button.setOnClickListener(corkyListener);
    ...
}

Anda juga akan merasa lebih praktis mengimplementasikan OnClickListener sebagai bagian dari Aktivitas. Hal ini akan menghindari beban kelas ekstra dan alokasi objek. Sebagai contoh:

Kotlin

class ExampleActivity : Activity(), OnClickListener {
  
    protected fun onCreate(savedValues: Bundle) {
        val button: Button = findViewById(R.id.corky)
        button.setOnClickListener(this)
    }

    // Implement the OnClickListener callback
    fun onClick(v: View) {
        // do something when the button is clicked
    }
}

Java

public class ExampleActivity extends Activity implements OnClickListener {
    protected void onCreate(Bundle savedValues) {
        ...
        Button button = (Button)findViewById(R.id.corky);
        button.setOnClickListener(this);
    }

    // Implement the OnClickListener callback
    public void onClick(View v) {
      // do something when the button is clicked
    }
    ...
}

Perhatikan bahwa callback onClick() dalam contoh di atas tidak memiliki nilai hasil, namun beberapa metode event listener lainnya harus menampilkan boolean. Alasan bergantung pada peristiwa. Untuk sebagian yang mengembalikan boolean, ini sebabnya:

  • onLongClick() - Ini menampilkan boolean untuk menunjukkan apakah Anda telah menggunakan peristiwa dan tidak boleh dilakukan lebih jauh. Yaitu, menampilkan true untuk menunjukkan apakah Anda telah menangani peristiwa dan harus berhenti di sini; menampilkan false jika Anda tidak menanganinya dan/atau kejadian harus melanjutkan ke on-click listener lainnya.
  • onKey() - Ini menampilkan boolean untuk menunjukkan apakah Anda telah menggunakan peristiwa dan tidak boleh dilakukan lebih jauh. Yaitu, menampilkan true untuk menunjukkan apakah Anda telah menangani kejadian dan harus berhenti di sini; menampilkan false jika Anda tidak menanganinya dan/atau peristiwa harus melanjutkan ke on-key listener lainnya.
  • onTouch() - Ini menampilkan boolean untuk menunjukkan apakah listener Anda telah menggunakan peristiwa ini. Yang penting adalah peristiwa ini bisa memiliki beberapa tindakan yang saling mengikuti. Jadi, jika Anda menampilkan false saat peristiwa tindakan turun diterima, itu menunjukkan bahwa Anda belum menggunakan peristiwa tersebut dan juga tidak tertarik dengan tindakan berikutnya dari peristiwa ini. Karena itu, Anda tidak akan diminta untuk melakukan tindakan lainnya dalam peristiwa, seperti isyarat jari, atau peristiwa kejadian naik yang akan terjadi.

Ingatlah bahwa kejadian tombol fisik selalu disampaikan ke View yang sedang fokus. Peristiwa ini dikirim mulai dari atas hierarki Tampilan, kemudian turun hingga tujuan yang sesuai. Jika Tampilan Anda (atau anak Tampilan Anda) saat ini sedang fokus, maka Anda dapat melihat peristiwa berpindah melalui metode. dispatchKeyEvent() Sebagai alternatif untuk menangkap peristiwa penting melalui Tampilan, Anda juga bisa menerima semua peristiwa dalam Aktivitas Anda dengan onKeyDown() dan onKeyUp().

Selain itu, saat memikirkan tentang masukan teks aplikasi Anda, ingatlah bahwa banyak perangkat yang hanya memiliki metode masukan perangkat lunak. Metode seperti itu tidak harus berbasis tombol; sebagian mungkin menggunakan masukan suara, tulisan tangan, dan seterusnya. Meskipun metode masukan menyajikan antarmuka seperti keyboard, itu umumnya tidak memicu lini peristiwa onKeyDown(). Anda sama sekali tidak boleh membuat UI yang mengharuskan penekanan tombol tertentu dikontrol kecuali jika Anda ingin membatasi aplikasi Anda pada perangkat yang memiliki keyboard fisik. Khususnya, jangan mengandalkan metode ini untuk memvalidasi masukan saat pengguna menekan tombol kembali; melainkan, gunakan tindakan seperti IME_ACTION_DONE untuk menandai metode masukan mengenai reaksi yang diharapkan aplikasi Anda, sehingga bisa mengubah UI-nya secara signifikan. Hindari anggapan tentang bagaimana metode masukan perangkat lunak seharusnya bekerja dan percayalah bahwa metode akan menyediakan teks yang sudah diformat bagi aplikasi Anda.

Catatan: Android akan memanggil event handler terlebih dahulu kemudian handler default yang sesuai dari definisi kelas. Karena itu, menampilkan true dari event listener ini akan menghentikan penyebaran peristiwa ke event listener lain dan juga akan memblokir callback ke event handler default di Tampilan. Pastikan bahwa Anda ingin mengakhiri kejadian saat mengembalikan true.

Event handler

Jika Anda membuat komponen kustom dari Tampilan, maka Anda dapat mendefinisikan penggunaan beberapa metode callback sebagai event handler default. Dalam dokumen tentang Komponen Tampilan Khusus, Anda akan melihat penggunaan beberapa callback umum untuk event handler, termasuk:

Ada beberapa metode lain yang harus Anda ketahui, yang bukan bagian dari kelas View, namun bisa berdampak langsung pada kemampuan Anda menangani kejadian. Jadi, saat mengelola kejadian yang lebih kompleks dalam layout, pertimbangkanlah metode-metode lain ini:

Mode sentuh

Saat pengguna menyusuri antarmuka pengguna dengan tombol arah atau trackball, Anda perlu memberikan fokus pada item tindakan (seperti tombol) agar pengguna bisa mengetahui apa yang akan menerima masukan. Akan tetapi jika perangkat memiliki kemampuan sentuh, dan pengguna mulai berinteraksi dengan antarmuka dengan menyentuhnya, maka Anda tidak perlu lagi menyorot item, atau memfokuskan pada Tampilan tertentu. Karena itu, ada mode untuk interaksi yang bernama "mode sentuh".

Untuk perangkat berkemampuan sentuh, setelah pengguna menyentuh layar, perangkat akan masuk ke mode sentuh. Dari titik ini dan selanjutnya, hanya Tampilan dengan isFocusableInTouchMode() true yang akan dapat fokus, seperti widget pengedit teks. Tampilan lain yang dapat disentuh, seperti tombol, tidak akan fokus jika disentuh; Tampilan ini akan langsung memicu on-click listener saat ditekan.

Kapan saja pengguna menekan tombol arah atau menggulir dengan trackball, perangkat akan keluar dari mode sentuh, dan mencari tampilan untuk difokuskan. Kini pengguna bisa melanjutkan interaksi dengan antarmuka pengguna tanpa menyentuh layar.

Status mode sentuh dipertahankan di seluruh sistem (semua jendela dan aktivitas). Untuk kueri status saat ini, Anda bisa memanggil isInTouchMode() untuk mengetahui apakah perangkat saat ini sedang dalam mode sentuh.

Menangani fokus

Framework ini akan menangani gerakan fokus rutin sebagai respons masukan pengguna. Ini termasuk mengubah fokus saat Tampilan dihapus atau disembunyikan, atau saat tersedia Tampilan baru. Tampilan menunjukkan kesediaannya untuk mengambil fokus melalui metode isFocusable(). Untuk mengubah apakah Tampilan bisa mengambil fokus, panggil setFocusable(). Saat dalam mode sentuh, Anda dapat melakukan kueri apakah Tampilan memungkinkan fokus dengan isFocusableInTouchMode(). Anda bisa mengubah ini dengan setFocusableInTouchMode().

Pada perangkat yang menjalankan Android 9 (API level 28) atau lebih tinggi, aktivitas tidak menetapkan fokus awal. Sebagai gantinya, Anda harus meminta fokus awal secara eksplisit, jika diinginkan.

Gerakan fokus berdasarkan pada algoritme yang mencari tetangga terdekat dalam arah yang diberikan. Dalam kasus yang jarang terjadi, algoritme default mungkin tidak cocok dengan perilaku yang diinginkan developer. Dalam situasi ini, Anda bisa menyediakan penggantian eksplisit dengan atribut XML berikut dalam file layout: nextFocusDown, nextFocusLeft, nextFocusRight, dan nextFocusUp. Tambahkan salah satu atribut ini ke Tampilan dari mana fokus keluar. Definisikan nilai atribut untuk menjadi ID Tampilan ke mana fokus harus diberikan. Sebagai contoh:

<LinearLayout
    android:orientation="vertical"
    ... >
  <Button android:id="@+id/top"
          android:nextFocusUp="@+id/bottom"
          ... />
  <Button android:id="@+id/bottom"
          android:nextFocusDown="@+id/top"
          ... />
</LinearLayout>

Biasanya, dalam layout vertikal ini, navigasi ke atas dari Tombol pertama tidak akan membawa ke mana pun, tidak pula akan menyusuri ke bawah dari Tombol kedua. Karena sekarang Tombol atas telah mendefinisikan Tombol bawah sebagai nextFocusUp (dan sebaliknya), fokus navigasi akan silih berganti dari atas ke bawah dan bawah ke atas.

Jika Anda ingin mendeklarasikan Tampilan sebagai dapat fokus dalam UI (jika biasanya tidak dapat fokus), tambahkan atribut XML android:focusable ke Tampilan, dalam deklarasi layout Anda. Setel nilai true. Anda juga bisa mendeklarasikan Tampilan sebagai dapat fokus saat dalam Mode Sentuh dengan android:focusableInTouchMode.

Untuk meminta View tertentu difokus, panggil requestFocus().

Untuk menyimak peristiwa fokus (diberi tahu jika Tampilan menerima atau kehilangan fokus), gunakan onFocusChange(), seperti yang dibahas di bagian Event listener.