Membuat komponen tampilan kustom

Mencoba cara Compose
Jetpack Compose adalah toolkit UI yang direkomendasikan untuk Android. Pelajari cara menggunakan tata letak di Compose.

Android menawarkan model canggih dan kuat yang terdiri dari berbagai komponen untuk membangun UI Anda, berdasarkan class tata letak dasar View dan ViewGroup. Platform ini berisi berbagai subclass View dan ViewGroup bawaan—yang disebut widget dan yang sesuai—yang dapat Anda gunakan untuk membuat UI.

Daftar sebagian widget yang tersedia mencakup Button, TextView, EditText, ListView, CheckBox, RadioButton, Gallery, Spinner, dan yang memiliki kegunaan khusus AutoCompleteTextView, ImageSwitcher, dan TextSwitcher.

Tata letak yang tersedia antara lain LinearLayout, FrameLayout, RelativeLayout, dan lainnya. Untuk contoh lainnya, lihat Tata letak umum.

Jika tidak ada widget atau tata letak bawaan yang memenuhi kebutuhan, Anda dapat membuatnya sendiri Subclass View. Jika Anda hanya perlu membuat penyesuaian kecil pada {i>widget<i} yang ada atau , Anda dapat membuat subclass widget atau tata letak dan mengganti metodenya.

Membuat subclass View sendiri memberi Anda kontrol yang akurat atas tampilan dan fungsi dari elemen layar. Untuk memberikan gambaran tentang kontrol yang Anda dapatkan dengan tampilan kustom, berikut adalah beberapa contoh hal yang dapat Anda lakukan dengan kebijakan tersebut:

  • Anda dapat membuat jenis View yang sepenuhnya dirender secara khusus—misalnya, "volume kontrol" {i>knob<i}, yang dirender menggunakan grafik 2D, yang menyerupai kontrol elektronik analog.
  • Anda dapat menggabungkan grup komponen View ke dalam satu komponen baru, mungkin untuk membuat sesuatu seperti kotak kombo (kombinasi daftar {i>pop-up<i} dan {i>free entri text field<i}), sebuah kontrol pemilih panel ganda (panel kiri dan kanan berisi daftar di masing-masing tempat Anda dapat menetapkan ulang item mana yang ada di daftar mana), dan seterusnya.
  • Anda dapat mengganti cara komponen EditText dirender di layar. Tujuan Aplikasi contoh NotePad menggunakan efek ini dengan baik untuk membuat halaman notepad bergaris.
  • Anda dapat mencatat peristiwa lain—seperti penekanan tombol—dan menanganinya dengan cara kustom, seperti seperti untuk game.

Bagian berikut menjelaskan cara membuat tampilan kustom dan menggunakannya di aplikasi Anda. Sebagai informasi referensi yang mendetail, lihat Class View.

Pendekatan dasar

Berikut ringkasan umum tentang hal-hal yang perlu diketahui untuk membuat View Anda sendiri komponen:

  1. Perluas class atau subclass View yang ada dengan class Anda sendiri.
  2. Ganti beberapa metode dari superclass. Metode superclass yang perlu diganti dimulai dengan on—misalnya, onDraw(), onMeasure(), dan onKeyDown(). Ini mirip dengan peristiwa on di Activity atau ListActivity yang Anda untuk siklus proses dan hook fungsi lainnya.
  3. Gunakan class ekstensi baru. Setelah selesai, Anda dapat menggunakan class ekstensi baru sebagai pengganti tampilan yang menjadi dasarnya.

Komponen yang disesuaikan sepenuhnya

Anda dapat membuat komponen grafis yang sepenuhnya disesuaikan yang muncul dengan cara apa pun kita inginkan. Mungkin Anda menginginkan pengukur VU grafis yang terlihat seperti pengukur analog lama, atau tampilan teks untuk bernyanyi bersama bola yang memantul bergerak di sepanjang kata saat Anda bernyanyi bersama mesin karaoke. Mungkin Anda ingin sesuatu yang tidak dapat dilakukan oleh komponen {i>built-in<i}, tidak peduli bagaimana Anda menggabungkannya.

Untungnya, Anda dapat membuat komponen yang terlihat dan berperilaku sesuai keinginan, hanya terbatas berdasarkan imajinasi Anda, ukuran layar, dan daya pemrosesan yang tersedia, ingatlah bahwa aplikasi mungkin harus berjalan pada perangkat dengan daya yang jauh lebih kecil daripada {i>desktop<i} Anda Infrastruktur Cloud.

Untuk membuat komponen yang disesuaikan sepenuhnya, pertimbangkan hal berikut:

  • Tampilan paling umum yang dapat diperluas adalah View, sehingga Anda biasanya memulai dengan memperluas ini untuk membuat komponen super baru.
  • Anda bisa menyediakan konstruktor, yang bisa mengambil atribut dan parameter dari XML, dan Anda bisa menggunakan atribut dan parameter Anda sendiri, seperti warna dan rentang VU meter atau lebar dan redaman jarum.
  • Anda mungkin ingin membuat pemroses peristiwa, pengakses properti, dan pengubah sendiri serta yang lebih canggih di class komponen Anda.
  • Anda hampir pasti ingin mengganti onMeasure() dan juga mungkin perlu ganti onDraw() jika Anda ingin komponen menampilkan sesuatu. Meskipun keduanya memiliki perilaku default, onDraw() default tidak melakukan apa pun, dan onMeasure() selalu menetapkan ukuran 100x100, yang mungkin tidak Anda inginkan.
  • Anda juga dapat mengganti metode on lainnya, sesuai kebutuhan.

Memperluas onDraw() dan onMeasure()

Metode onDraw() memberikan Canvas, yang dapat Anda mengimplementasikan apa pun yang Anda inginkan: grafis 2D, komponen standar atau kustom lainnya, teks bergaya, atau hal lain yang bisa Anda pikirkan.

onMeasure() sedikit lebih terlibat. onMeasure() adalah bagian penting dari kontrak rendering antara komponen Anda dan kontainernya. onMeasure() harus diabaikan untuk melaporkan pengukuran bagian-bagian yang ada di dalamnya secara efisien dan akurat. Ini adalah dibuat sedikit lebih kompleks dengan persyaratan batas dari induk—yang diteruskan ke onMeasure()—dan dengan persyaratan untuk memanggil Metode setMeasuredDimension() dengan lebar dan tinggi yang diukur setelah yang dihitung. Jika Anda tidak memanggil metode ini dari metode onMeasure() yang diganti, menghasilkan pengecualian pada waktu pengukuran.

Pada level yang tinggi, penerapan onMeasure() akan terlihat seperti ini:

  • Metode onMeasure() yang diganti dipanggil dengan lebar dan tinggi spesifikasi, yang diperlakukan sebagai persyaratan untuk pembatasan lebar dan tinggi pengukuran yang Anda hasilkan. widthMeasureSpec dan heightMeasureSpec keduanya adalah kode bilangan bulat yang mewakili dimensi. Referensi lengkap tentang jenis batasan yang mungkin dibutuhkan oleh spesifikasi ini, bisa ditemukan di dokumentasi referensi pada View.onMeasure(int, int) Dokumentasi referensi ini juga menjelaskan keseluruhan operasi pengukuran.
  • Metode onMeasure() komponen Anda menghitung lebar dan tinggi pengukuran, yang diperlukan untuk merender komponen. URL harus tetap berada dalam spesifikasi yang diteruskan walaupun bisa melebihi mereka. Dalam hal ini, orang tua dapat memilih tindakan yang akan dilakukan, termasuk memotong, men-scroll, menampilkan pengecualian, atau meminta onMeasure() mencoba lagi, mungkin dengan spesifikasi pengukuran yang berbeda.
  • Saat lebar dan tinggi dihitung, panggil metode setMeasuredDimension(int width, int height) dengan metode pengukuran. Kegagalan dalam melakukan langkah ini akan menghasilkan pengecualian.

Berikut ringkasan metode standar lainnya yang dipanggil framework pada tampilan:

Kategori Metode Deskripsi
Kreasi Konstruktor Ada bentuk konstruktor yang dipanggil bila tampilan dibuat dari kode dan formulir yang dipanggil saat tampilan di-inflate dari file tata letak. Bentuk kedua mengurai dan menerapkan atribut yang ditentukan dalam file tata letak.
onFinishInflate() Dipanggil setelah tampilan dan semua turunannya di-inflate dari XML.
Tata Letak onMeasure(int, int) Dipanggil guna menentukan persyaratan ukuran untuk tampilan ini dan semua turunannya.
onLayout(boolean, int, int, int, int) Dipanggil saat tampilan ini harus menetapkan ukuran dan posisi ke semua turunannya.
onSizeChanged(int, int, int, int) Dipanggil saat ukuran tampilan ini diubah.
Gambar onDraw(Canvas) Dipanggil saat tampilan harus merender kontennya.
Pemrosesan peristiwa onKeyDown(int, KeyEvent) Dipanggil saat peristiwa tombol turun terjadi.
onKeyUp(int, KeyEvent) Dipanggil saat peristiwa tombol ke atas terjadi.
onTrackballEvent(MotionEvent) Dipanggil saat peristiwa gerakan trackball terjadi.
onTouchEvent(MotionEvent) Dipanggil saat peristiwa gerakan layar sentuh terjadi.
Fokus onFocusChanged(boolean, int, Rect) Dipanggil saat tampilan mendapatkan atau kehilangan fokus.
onWindowFocusChanged(boolean) Dipanggil saat jendela yang berisi tampilan mendapatkan atau kehilangan fokus.
Pemasangan onAttachedToWindow() Dipanggil saat tampilan dilampirkan ke jendela.
onDetachedFromWindow() Dipanggil saat tampilan dilepas dari jendelanya.
onWindowVisibilityChanged(int) Dipanggil saat visibilitas jendela yang berisi tampilan diubah.

Kontrol gabungan

Jika Anda tidak ingin membuat komponen yang sepenuhnya disesuaikan tetapi ingin meletakkan komponen yang dapat digunakan kembali yang terdiri dari grup kontrol yang ada, lalu membuat komponen komponen (atau kontrol gabungan) mungkin lebih baik. Singkatnya, hal ini menyatukan beberapa kontrol atau tampilan atomik menjadi sekelompok item logis yang dapat diperlakukan sebagai satu hal. Misalnya, kotak kombo dapat berupa kombinasi dari kolom EditText baris tunggal dan tombol yang berdekatan dengan daftar {i>pop-up<i} terlampir. Jika pengguna mengetuk tombol dan memilih sesuatu dari daftar, kolom EditText akan diisi, tetapi pengguna juga dapat mengetik sesuatu langsung ke EditText jika diinginkan.

Di Android, ada dua tampilan lain yang tersedia untuk melakukan ini: Spinner dan AutoCompleteTextView. Terlepas dari itu, konsep untuk kotak kombo ini adalah contoh yang baik.

Untuk membuat komponen gabungan, lakukan hal berikut:

  • Sama seperti dengan Activity, gunakan pendekatan deklaratif (berbasis XML) untuk membuat komponen yang ditampung atau menyusunnya menjadi bertingkat secara terprogram dari kode Anda. Tujuan titik awal yang biasa adalah Layout, jadi buat class yang memperluas Layout. Dalam kasus kotak kombo, Anda dapat menggunakan LinearLayout dengan orientasi horizontal. Anda dapat menyusun bertingkat tata letak lain di dalamnya, sehingga komponen gabungan dapat kompleks dan terstruktur secara bebas.
  • Dalam konstruktor untuk class baru, ambil parameter apa pun yang diharapkan oleh superclass dan teruskan mereka melalui konstruktor superclass terlebih dahulu. Kemudian, Anda dapat menyiapkan tampilan lain untuk digunakan dalam komponen baru. Di sinilah Anda membuat kolom EditText dan daftar pop-up. Anda dapat memperkenalkan atribut dan parameter sendiri ke dalam XML yang yang dapat ditarik dan digunakan.
  • Secara opsional, buat pemroses untuk peristiwa yang mungkin dihasilkan oleh tampilan yang dimuat Anda. Contohnya adalah untuk pemroses klik item daftar guna memperbarui konten EditText jika pilihan daftar dibuat.
  • Secara opsional, buat properti Anda sendiri dengan pengakses dan pengubah. Misalnya, biarkan Nilai EditText ditetapkan di awal dalam komponen dan mengkueri kontennya saat diperlukan.
  • Atau, ganti onDraw() dan onMeasure(). Ini biasanya tidak diperlukan ketika memperluas Layout, karena tata letak memiliki perilaku default yang mungkin berfungsi dengan baik.
  • Atau, ganti metode on lain, seperti onKeyDown(), misalnya untuk memilih nilai {i>default<i} dari daftar {i>popup<i} kotak kombo ketika tombol tertentu diketuk.

Ada beberapa keuntungan dalam menggunakan Layout sebagai dasar untuk kontrol kustom, termasuk yang berikut:

  • Anda bisa menetapkan tata letak menggunakan file XML deklaratif, sama seperti layar aktivitas, atau Anda bisa membuat tampilan secara terprogram dan memasukkannya ke dalam tata letak dari kode Anda.
  • Metode onDraw() dan onMeasure(), serta sebagian besar metode lainnya Metode on memiliki perilaku yang sesuai, sehingga Anda tidak perlu menggantinya.
  • Anda dapat dengan cepat membuat tampilan gabungan yang kompleks secara bebas dan menggunakannya kembali seolah-olah komponen tunggal.

Mengubah jenis tampilan yang ada

Jika ada komponen yang mirip dengan yang Anda inginkan, Anda dapat memperluas komponen tersebut dan mengganti perilaku yang ingin Anda ubah. Anda dapat melakukan semua hal dengan antarmuka yang disesuaikan Namun, dengan memulai dari class yang lebih khusus dalam hierarki View, Anda dapat mendapatkan beberapa perilaku yang melakukan apa yang Anda inginkan secara gratis.

Misalnya, NotePad aplikasi contoh menunjukkan banyak aspek dalam menggunakan platform Android. Di antaranya adalah memperluas Tampilan EditText untuk membuat notepad bergaris. Ini bukan contoh yang sempurna, dan API untuk melakukan ini mungkin mengubah, tetapi hal itu menunjukkan prinsip-prinsipnya.

Jika Anda belum melakukannya, impor contoh NotePad ke Android Studio atau lihat sumber menggunakan tautan yang disediakan. Secara khusus, lihat definisi LinedEditText di NoteEditor.java .

Berikut beberapa hal yang perlu diketahui dalam file ini:

  1. Definisi

    Class ditentukan dengan baris berikut:
    public static class LinedEditText extends EditText

    LinedEditText didefinisikan sebagai class dalam dalam NoteEditor aktivitas, tetapi bersifat publik sehingga dapat diakses sebagai NoteEditor.LinedEditText dari luar class NoteEditor.

    Selain itu, LinedEditText adalah static, yang berarti kode tersebut tidak menghasilkan yang disebut “metode sintetik{i>”<i} yang memungkinkannya mengakses data dari class induk. Ini berarti berperilaku sebagai class terpisah, bukan sesuatu yang sangat terkait dengan NoteEditor. Ini adalah cara yang lebih bersih untuk membuat class dalam jika class tersebut tidak memerlukan akses ke status dari kelas luar. Class ini membuat class yang dihasilkan tetap kecil dan dapat digunakan dengan mudah dari Google Cloud Platform.

    LinedEditText memperluas EditText, yang merupakan tampilan yang akan disesuaikan dalam kasus ini. Setelah Anda selesai, class baru dapat menggantikan EditText yang normal {i>view<i}.

  2. Inisialisasi class

    Seperti biasa, super dipanggil terlebih dahulu. Ini bukan konstruktor default, tetapi merupakan diparameterisasi. EditText dibuat dengan parameter ini saat di-inflate dari file tata letak XML. Jadi, konstruktor perlu mengambilnya dan meneruskannya ke konstruktor superclass.

  3. Metode yang diganti

    Contoh ini hanya mengganti metode onDraw(), tetapi Anda mungkin perlu mengganti lainnya saat Anda membuat komponen kustom Anda sendiri.

    Untuk contoh ini, mengganti metode onDraw() memungkinkan Anda melukis garis biru di kanvas tampilan EditText. Kanvas diteruskan ke ruang Metode onDraw(). Metode super.onDraw() dipanggil sebelum metode tersebut berakhir. Metode superclass harus dipanggil. Dalam hal ini, panggil di akhir setelah Anda melukis garis-garis yang ingin Anda sertakan.

  4. Komponen kustom

    Anda sekarang memiliki komponen kustom, tetapi bagaimana cara menggunakannya? Dalam contoh NotePad, kustom digunakan langsung dari tata letak deklaratif, jadi lihat note_editor.xml dalam res/layout folder:

    <view xmlns:android="http://schemas.android.com/apk/res/android"
        class="com.example.android.notepad.NoteEditor$LinedEditText"
        android:id="@+id/note"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:padding="5dp"
        android:scrollbars="vertical"
        android:fadingEdge="vertical"
        android:gravity="top"
        android:textSize="22sp"
        android:capitalize="sentences"
    />
    

    Komponen kustom dibuat sebagai tampilan generik di XML, dan class ditetapkan menggunakan paket lengkap. Kelas dalam yang Anda tentukan direferensikan menggunakan Notasi NoteEditor$LinedEditText, yang merupakan cara standar untuk merujuk ke bagian dalam dalam bahasa pemrograman Java.

    Jika komponen tampilan kustom tidak didefinisikan sebagai class dalam, Anda dapat mendeklarasikan tampilan komponen dengan nama elemen XML dan mengecualikan atribut class. Contoh:

    <com.example.android.notepad.LinedEditText
      id="@+id/note"
      ... />
    

    Perlu diketahui bahwa class LinedEditText kini merupakan file class terpisah. Jika berada di class NoteEditor, teknik ini tidak akan berfungsi.

    Atribut dan parameter lain dalam definisi adalah atribut dan parameter yang diteruskan ke konstruktor komponen lalu diteruskan ke konstruktor EditText, sehingga parameter tersebut sama dengan yang Anda gunakan untuk tampilan EditText. Kita bisa menambahkan parameter Anda sendiri.

Membuat komponen kustom hanya serumit yang Anda perlukan.

Komponen yang lebih canggih dapat menggantikan lebih banyak metode on dan memperkenalkan metode helpernya sendiri, yang secara substansial menyesuaikan properti dan perilakunya. Satu-satunya batasan adalah imajinasi dan apa yang Anda perlukan komponennya untuk melakukannya.