Android menawarkan model canggih dan andal yang terbagi menjadi komponen terpisah untuk mem-build UI, berdasarkan
class tata letak dasar
View dan
ViewGroup. Platform ini mencakup berbagai subclass View dan ViewGroup bawaan—masing-masing disebut widget dan tata letak—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 membuat subclass View sendiri. Jika Anda hanya perlu melakukan sedikit penyesuaian pada widget atau tata letak yang ada, Anda dapat membuat subclass widget atau tata letak dan mengganti metodenya.
Pembuatan subclass View sendiri memberi Anda kontrol yang akurat terhadap tampilan dan
fungsi elemen layar. Untuk memberi gambaran terkait kontrol yang Anda dapatkan dengan tampilan kustom, berikut
beberapa contoh hal yang dapat Anda lakukan dengan tampilan kustom:
-
Anda dapat membuat jenis
Viewyang sepenuhnya dirender secara kustom—misalnya, tombol "kontrol volume", yang dirender menggunakan grafis 2D, yang menyerupai kontrol elektronik analog. -
Anda dapat menggabungkan sekelompok komponen
Viewmenjadi satu komponen baru, mungkin untuk membuat sesuatu seperti kotak kombinasi (kombinasi daftar pop-up dan kolom teks entri bebas), kontrol pemilih panel ganda (panel kiri dan kanan dengan daftar di setiap panel tempat Anda dapat menetapkan ulang item mana yang ada di daftar mana), dan sebagainya. -
Anda dapat mengganti cara komponen
EditTextdirender di layar. Aplikasi contoh NotePad menggunakan efek yang baik ini untuk membuat halaman notepad bergaris. - Anda dapat mencatat peristiwa lain—seperti penekanan tombol—dan menanganinya dengan cara kustom, seperti untuk game.
Bagian berikut menjelaskan cara membuat tampilan kustom dan menggunakannya di aplikasi Anda. Untuk mengetahui informasi referensi yang mendetail, lihat class View.
Pendekatan dasar
Berikut ringkasan umum tentang hal yang perlu diketahui untuk membuat komponen View
Anda sendiri:
-
Perluas class atau subclass
Viewyang ada dengan class Anda sendiri. -
Ganti beberapa metode dari superclass. Metode superclass yang perlu diganti dimulai dengan
on—misalnya,onDraw(),onMeasure(), danonKeyDown(). Ini mirip dengan peristiwaondiActivityatauListActivityyang Anda ganti untuk siklus proses dan hook fungsi lainnya. - 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 sesuai keinginan Anda. Mungkin Anda menginginkan VU meter grafis yang tampak seperti pengukur analog lama, atau tampilan teks untuk menyanyikan lagu, dengan bola yang melambung bergerak sesuai dengan kata saat Anda bernyanyi bersama mesin karaoke. Anda mungkin menginginkan sesuatu yang tidak dapat dilakukan oleh komponen bawaan, bagaimana pun Anda menggabungkannya.
Untungnya, Anda dapat membuat komponen yang terlihat dan berperilaku sesuai keinginan Anda, yang hanya dibatasi oleh imajinasi Anda, ukuran layar, dan daya pemrosesan yang tersedia, dengan mengingat bahwa aplikasi Anda mungkin harus berjalan di perangkat dengan daya yang jauh lebih rendah daripada workstation desktop Anda.
Untuk membuat komponen yang disesuaikan sepenuhnya, pertimbangkan hal berikut:
-
Tampilan paling umum yang dapat Anda perluas adalah
View, jadi biasanya Anda akan memulai dengan memperluas tampilan ini untuk membuat komponen super baru. - Anda dapat menyediakan konstruktor, yang dapat mengambil atribut dan parameter dari XML, dan Anda dapat 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 perilaku yang lebih rumit dalam class komponen.
-
Kemungkinan besar Anda ingin mengganti
onMeasure()dan juga perlu menggantionDraw()jika ingin agar komponen menampilkan sesuatu. Meskipun keduanya memiliki perilaku default,onDraw()default tidak melakukan apa pun, danonMeasure()default selalu menetapkan ukuran 100x100, yang mungkin tidak Anda inginkan. -
Anda juga dapat mengganti metode
onlainnya sesuai kebutuhan.
Memperluas onDraw() dan onMeasure()
Metode onDraw() memberikan
Canvas yang dapat Anda gunakan untuk
mengimplementasikan apa pun yang Anda inginkan: grafis 2D, komponen standar atau kustom lain, teks bergaya, atau
apa pun yang Anda inginkan.
onMeasure() sedikit lebih terlibat. onMeasure() adalah bagian penting
dari kontrak rendering antara komponen Anda dan container-nya. onMeasure() harus diganti agar dapat melaporkan pengukuran bagian-bagian yang terdapat di dalamnya secara efisien dan akurat. Hal ini
dibuat sedikit lebih kompleks oleh persyaratan batas dari induk—yang diteruskan ke
metode onMeasure()—dan oleh persyaratan untuk memanggil
metode setMeasuredDimension() dengan lebar dan tinggi yang diukur setelah
dihitung. Jika Anda tidak memanggil metode ini dari metode onMeasure() yang telah diganti, hal ini
akan menghasilkan pengecualian pada waktu pengukuran.
Pada level yang tinggi, implementasi onMeasure() akan terlihat seperti ini:
-
Metode
onMeasure()yang telah diganti dipanggil dengan spesifikasi lebar dan tinggi, yang diperlakukan sebagai persyaratan untuk batasan terhadap pengukuran lebar dan tinggi yang Anda hasilkan. ParameterwidthMeasureSpecdanheightMeasureSpecadalah kode bilangan bulat yang mewakili dimensi. Referensi lengkap tentang jenis pembatasan yang dapat dijadikan persyaratan oleh spesifikasi ini dapat ditemukan di dokumentasi referensi dalamView.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. Metode ini harus mencoba tetap dalam spesifikasi yang diteruskan, meskipun dapat melebihi spesifikasi tersebut. Dalam hal ini, induk dapat memilih apa yang harus dilakukan, termasuk menyesuaikan, men-scroll, melempar pengecualian, atau memintaonMeasure()untuk mencoba lagi, mungkin dengan spesifikasi pengukuran yang berbeda. -
Setelah lebar dan tinggi dihitung, panggil metode
setMeasuredDimension(int width, int height)dengan pengukuran yang telah dihitung. Jika tidak dilakukan, akan muncul pengecualian.
Berikut ringkasan metode standar lainnya yang dipanggil framework pada tampilan:
| Kategori | Metode | Deskripsi |
|---|---|---|
| Kreasi | Konstruktor | Ada bentuk konstruktor yang dipanggil saat tampilan dibuat dari kode dan bentuk yang dipanggil saat tampilan di-inflate dari file tata letak. Bentuk kedua mengurai dan menerapkan atribut yang ditentukan dalam file tata letak. |
|
Dipanggil setelah tampilan dan semua turunannya di-inflate dari XML. | |
| Tata Letak | |
Dipanggil guna menentukan persyaratan ukuran untuk tampilan ini dan semua turunannya. |
|
Dipanggil saat tampilan ini harus menetapkan ukuran dan posisi ke semua turunannya. | |
|
Dipanggil saat ukuran tampilan ini diubah. | |
| Gambar | |
Dipanggil saat tampilan harus merender kontennya. |
| Pemrosesan peristiwa | |
Dipanggil saat peristiwa tombol ke bawah terjadi. |
|
Dipanggil saat peristiwa tombol ke atas terjadi. | |
|
Dipanggil saat peristiwa gerakan trackball terjadi. | |
|
Dipanggil saat peristiwa gerakan layar sentuh terjadi. | |
| Fokus | |
Dipanggil saat tampilan mendapatkan atau kehilangan fokus. |
|
Dipanggil saat jendela yang berisi tampilan mendapatkan atau kehilangan fokus. | |
| Pemasangan | |
Dipanggil saat tampilan dilampirkan ke jendela. |
|
Dipanggil saat tampilan dilepas dari jendelanya. | |
|
Dipanggil saat visibilitas jendela yang berisi tampilan diubah. |
Kontrol gabungan
Jika Anda tidak ingin membuat komponen yang disesuaikan sepenuhnya, tetapi ingin
menyatukan komponen yang dapat digunakan kembali yang terdiri dari sekumpulan kontrol yang sudah ada, maka membuat komponen gabungan (atau kontrol gabungan) mungkin yang terbaik. Singkatnya, tindakan ini akan menyatukan sejumlah kontrol atau tampilan yang lebih kecil menjadi sekumpulan item logis yang dapat diperlakukan sebagai satu item.
Misalnya, kotak kombinasi dapat berupa kombinasi kolom EditText satu baris
dan tombol yang berdekatan dengan daftar pop-up terlampir. Jika pengguna mengetuk tombol dan memilih sesuatu dari
daftar, pilihan Anda akan mengisi kolom EditText, tetapi pengguna juga dapat mengetik sesuatu
langsung ke kolom EditText jika menginginkannya.
Di Android, ada dua tampilan lain yang tersedia untuk melakukan hal ini: Spinner dan
AutoCompleteTextView. Terlepas dari itu, konsep kotak kombinasi ini adalah contoh yang baik.
Untuk membuat komponen compound, lakukan hal berikut:
-
Seperti
Activity, gunakan pendekatan deklaratif (berbasis XML) untuk membuat komponen yang terdapat di dalamnya atau menyarangkannya secara terprogram dari kode Anda. Titik awal yang umum adalahLayout, jadi buat class yang memperluasLayout. Untuk kotak kombinasi, Anda dapat menggunakanLinearLayoutdengan orientasi horizontal. Anda dapat menyarangkan tata letak lain di dalamnya, sehingga komponen compound dapat menjadi kompleks dan terstruktur secara bebas. -
Dalam konstruktor untuk class baru, ambil parameter apa pun yang diharapkan superclass dan teruskan
parameter tersebut melalui konstruktor superclass terlebih dahulu. Kemudian, Anda dapat menyiapkan tampilan lain untuk digunakan
dalam komponen baru. Di sinilah Anda membuat kolom
EditTextdan daftar pop-up. Anda dapat memperkenalkan atribut dan parameter sendiri ke XML yang dapat ditarik dan digunakan oleh konstruktor. -
Secara opsional, buat pemroses untuk peristiwa yang dapat dihasilkan oleh tampilan yang ada di dalamnya. Contohnya adalah
metode pemroses untuk pemroses klik item daftar guna memperbarui konten
EditTextjika pilihan daftar dibuat. -
Atau, buat properti Anda sendiri dengan pengakses dan pengubah. Misalnya, izinkan nilai
EditTextditetapkan di awal dalam komponen dan kueri untuk kontennya saat diperlukan. -
Secara opsional, ganti
onDraw()danonMeasure(). Hal ini biasanya tidak diperlukan saat memperluasLayout, karena tata letak memiliki perilaku default yang kemungkinan berfungsi dengan baik. -
(Opsional) Ganti metode
onlain, sepertionKeyDown(), misalnya untuk memilih nilai default tertentu dari daftar pop-up kotak kombinasi saat tombol tertentu diketuk.
Ada keuntungan menggunakan Layout sebagai dasar untuk kontrol kustom, termasuk yang berikut:
- Anda dapat menentukan tata letak menggunakan file XML deklaratif, seperti pada layar aktivitas, atau Anda dapat membuat tampilan secara terprogram dan menyarangkannya ke tata letak dari kode.
-
Metode
onDraw()danonMeasure(), serta sebagian besar metodeonlainnya, 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 tampilan tersebut merupakan 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 yang Anda lakukan dengan komponen yang disesuaikan sepenuhnya, tetapi dengan memulai dengan class yang lebih khusus dalam hierarki View, Anda bisa mendapatkan beberapa perilaku yang melakukan apa yang Anda inginkan secara gratis.
Misalnya, aplikasi contoh
NotePad
menunjukkan banyak aspek penggunaan platform Android. Di antaranya adalah memperluas tampilan
EditText untuk membuat notepad bergaris. Ini bukan contoh yang ideal, dan API untuk
melakukannya mungkin berubah, tetapi contoh ini menunjukkan prinsipnya.
Jika belum, impor sampel NotePad ke Android Studio atau lihat
sumber menggunakan link yang tersedia. Secara khusus, lihat definisi LinedEditText
dalam file
NoteEditor.java.
Berikut beberapa hal yang perlu diketahui dalam file ini:
-
Definisi
Class didefinisikan dengan baris berikut:
public static class LinedEditText extends EditTextLinedEditTextdidefinisikan sebagai class dalam di dalam aktivitasNoteEditor, tetapi bersifat publik sehingga dapat diakses sebagaiNoteEditor.LinedEditTextdari luar classNoteEditor.Selain itu,
LinedEditTextadalahstatic, yang berarti tidak menghasilkan "metode sintesis" yang memungkinkannya mengakses data dari class induk. Artinya, class ini berperilaku sebagai class terpisah, bukan sesuatu yang sangat terkait denganNoteEditor. Ini adalah cara yang lebih sederhana untuk membuat class dalam jika class tersebut tidak memerlukan akses ke status dari class luar. Hal ini membuat class yang dihasilkan tetap kecil dan memungkinkannya digunakan dengan mudah dari class lain.LinedEditTextmemperluasEditText, yang merupakan tampilan yang akan disesuaikan dalam kasus ini. Setelah selesai, class baru dapat menggantikan tampilanEditTextnormal. -
Inisialisasi class
Seperti biasa, super dipanggil terlebih dahulu. Ini bukan konstruktor default, tetapi merupakan konstruktor berparameter.
EditTextdibuat dengan parameter ini saat di-inflate dari file tata letak XML. Oleh karena itu, konstruktor harus mengambil dan meneruskannya ke konstruktor superclass. -
Metode yang diganti
Contoh ini hanya mengganti metode
onDraw(), tetapi Anda mungkin perlu mengganti metode lain saat membuat komponen kustom sendiri.Untuk contoh ini, penggantian metode
onDraw()memungkinkan Anda menggambar garis biru di kanvas tampilanEditText. Kanvas diteruskan ke metodeonDraw()yang diganti. Metodesuper.onDraw()dipanggil sebelum metode berakhir. Metode superclass harus dipanggil. Dalam hal ini, panggil di akhir setelah Anda menggambar garis yang ingin disertakan. -
Komponen kustom
Sekarang Anda memiliki komponen kustom, tetapi bagaimana cara menggunakannya? Dalam contoh NotePad, komponen kustom digunakan langsung dari tata letak deklaratif, jadi lihat
note_editor.xmldi folderres/layout:<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 umum di XML, dan class ditentukan menggunakan paket lengkap. Class dalam yang Anda tentukan direferensikan menggunakan notasi
NoteEditor$LinedEditText, yang merupakan cara standar untuk mereferensikan class dalam dalam bahasa pemrograman Java.Jika komponen tampilan kustom Anda tidak didefinisikan sebagai class dalam, Anda dapat mendeklarasikan komponen tampilan dengan nama elemen XML dan mengecualikan atribut
class. Contoh:<com.example.android.notepad.LinedEditText id="@+id/note" ... />
Perlu diketahui bahwa class
LinedEditTextkini merupakan file class terpisah. Jika class disarangkan di classNoteEditor, teknik ini tidak akan berfungsi.Atribut dan parameter lain dalam definisi tersebut adalah atribut dan parameter yang diteruskan ke konstruktor komponen kustom, lalu diteruskan ke konstruktor
EditText, sehingga merupakan parameter yang sama yang Anda gunakan untuk tampilanEditText. Anda juga dapat menambahkan parameter Anda sendiri.
Proses pembuatan komponen kustom memang sederhana.
Komponen yang lebih rumit dapat menggantikan lebih banyak metode on dan memperkenalkan
metode helper-nya sendiri, yang secara substansial menyesuaikan properti dan perilakunya. Satu-satunya batasan adalah
imajinasi Anda dan apa yang perlu dilakukan komponen.