Android menawarkan model canggih dan canggih yang terdiri atas berbagai komponen untuk membangun UI, berdasarkan
class tata letak dasar
View
dan
ViewGroup
. Platform ini menyertakan
berbagai subclass View
dan ViewGroup
bawaan—yang masing-masing disebut widget dan
tata letak—yang dapat Anda gunakan untuk membuat UI.
Sebagian daftar widget yang tersedia mencakup Button
,
TextView
,
EditText
,
ListView
,
CheckBox
,
RadioButton
,
Gallery
,
Spinner
, dan AutoCompleteTextView
,
ImageSwitcher
, dan
TextSwitcher
untuk tujuan yang lebih khusus.
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 hanya perlu membuat penyesuaian kecil pada widget atau
tata letak yang ada, Anda dapat membuat subclass widget atau tata letak dan mengganti metodenya.
Membuat subclass View
sendiri memberi Anda kontrol yang akurat terhadap tampilan dan
fungsi elemen layar. Untuk memberikan gambaran tentang kontrol yang Anda dapatkan dengan tampilan kustom, berikut
beberapa contoh yang dapat Anda lakukan dengan tampilan kustom:
-
Anda dapat membuat jenis
View
yang sepenuhnya dirender secara kustom—misalnya, tombol "kontrol volume" yang dirender menggunakan grafis 2D, yang menyerupai kontrol elektronik analog. -
Anda dapat menggabungkan grup komponen
View
menjadi satu komponen baru, mungkin untuk membuat sesuatu seperti kotak kombinasi (kombinasi daftar pop-up dan kolom teks entri bebas), kontrol pemilih dua panel (panel kiri dan kanan dengan daftar di setiap komponen tempat Anda dapat menetapkan ulang item mana yang berada dalam daftar), dan seterusnya. -
Anda dapat mengganti cara komponen
EditText
dirender di layar. Aplikasi contoh NotePad menggunakan ini untuk efek yang baik guna membuat halaman notepad bergaris. - Anda dapat mencatat peristiwa lainnya—seperti penekanan tombol—dan menanganinya dengan cara kustom, seperti untuk game.
Bagian berikut menjelaskan cara membuat tampilan kustom dan menggunakannya di aplikasi Anda. Untuk
informasi referensi mendetail, lihat
class View
.
Pendekatan dasar
Berikut adalah ringkasan umum tentang hal-hal yang perlu diketahui untuk membuat komponen View
Anda sendiri:
-
Perluas class atau subclass
View
yang 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 peristiwaon
diActivity
atauListActivity
yang Anda ganti untuk siklus proses dan hook fungsi lainnya. - Gunakan class ekstensi baru. Setelah selesai, Anda dapat menggunakan class ekstensi yang baru sebagai pengganti tampilan yang menjadi dasarnya.
Komponen yang disesuaikan sepenuhnya
Anda dapat membuat komponen grafis yang sepenuhnya disesuaikan dan muncul sesuai keinginan Anda. Mungkin Anda menginginkan VU meter grafis yang terlihat seperti pengukur analog lama, atau tampilan teks untuk menyanyi bersama dengan bola yang memantul mengikuti kata-kata saat Anda bernyanyi bersama mesin karaoke. Anda mungkin menginginkan sesuatu yang tidak dapat dilakukan komponen bawaan, bagaimana pun Anda menggabungkannya.
Untungnya, Anda dapat membuat komponen yang terlihat dan berperilaku sesuai keinginan, hanya dengan imajinasi Anda, ukuran layar, dan daya pemrosesan yang tersedia. Perlu diingat bahwa aplikasi Anda mungkin harus berjalan pada sesuatu dengan daya yang jauh lebih sedikit daripada workstation desktop.
Untuk membuat komponen yang disesuaikan sepenuhnya, pertimbangkan hal berikut:
-
Tampilan paling umum yang dapat diperluas adalah
View
, jadi biasanya Anda 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 canggih di class komponen.
-
Anda hampir pasti ingin mengganti
onMeasure()
dan juga perlu menggantionDraw()
jika ingin 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
on
lainnya, sesuai kebutuhan.
Memperluas onDraw() dan onMeasure()
Metode onDraw()
memberikan
Canvas
tempat Anda dapat
mengimplementasikan apa pun yang Anda inginkan: grafis 2D, komponen standar atau kustom lainnya, teks bergaya, atau
apa pun yang bisa Anda pikirkan.
onMeasure()
sedikit lebih terlibat. onMeasure()
adalah bagian penting
dari kontrak rendering antara komponen Anda dan container-nya. onMeasure()
harus
diganti untuk melaporkan pengukuran bagian yang ada di dalamnya secara efisien dan akurat. Hal ini
dibuat sedikit lebih kompleks dengan persyaratan batas dari induk—yang diteruskan ke
metode onMeasure()
—dan oleh persyaratan untuk memanggil
metode setMeasuredDimension()
dengan lebar dan tinggi terukur setelah
dihitung. Jika Anda tidak memanggil metode ini dari metode onMeasure()
yang diganti, metode
tersebut akan menghasilkan pengecualian pada waktu pengukuran.
Pada level yang tinggi, penerapan 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. ParameterwidthMeasureSpec
danheightMeasureSpec
merupakan kode bilangan bulat yang mewakili dimensi. Referensi lengkap tentang jenis batasan yang mungkin diwajibkan oleh spesifikasi ini dapat ditemukan dalam dokumentasi referensi padaView.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. Pengujian harus tetap berada dalam spesifikasi yang diteruskan, meskipun dapat melebihi spesifikasi tersebut. Dalam hal ini, induk dapat memilih tindakan yang harus dilakukan, termasuk clipping, men-scroll, menampilkan 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. 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 saat tampilan dibuat dari kode dan bentuk yang dipanggil bila tampilan di-inflate dari file tata letak. Formulir kedua mengurai dan menerapkan atribut yang ditetapkan dalam file tata letak. |
|
Dipanggil setelah tampilan dan semua turunannya di-inflate dari XML. | |
Tata Letak |
|
Dipanggil untuk 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 turun 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 sepenuhnya disesuaikan, tetapi ingin menyusun
komponen yang dapat digunakan kembali yang terdiri dari grup kontrol yang sudah ada, membuat komponen
majemuk (atau kontrol gabungan) mungkin adalah pilihan terbaik. Singkatnya, hal ini menyatukan sejumlah kontrol atau tampilan yang lebih
atomik ke dalam grup logis item yang dapat diperlakukan sebagai satu hal.
Misalnya, kotak kombinasi dapat berupa kombinasi dari satu kolom EditText
baris
dan tombol yang berdekatan dengan daftar pop-up terlampir. Jika pengguna mengetuk tombol tersebut dan memilih sesuatu dari
daftar, kolom EditText
akan diisi, tetapi pengguna juga dapat mengetik sesuatu
secara langsung ke dalam EditText
jika mau.
Di Android, ada dua tampilan lain yang tersedia untuk melakukan hal 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
Activity
, gunakan pendekatan deklaratif (berbasis XML) untuk membuat komponen yang terdapat di dalamnya atau menyarangkannya secara terprogram dari kode Anda. Titik awal yang biasa adalahLayout
atau sejenisnya, jadi buat class yang memperluasLayout
. Dalam kasus kotak kombinasi, Anda dapat menggunakanLinearLayout
dengan orientasi horizontal. Anda dapat menyusun bertingkat tata letak lain di dalamnya, sehingga komponen gabungan 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
EditText
dan daftar pop-up. Anda dapat memperkenalkan atribut dan parameter Anda sendiri ke dalam XML yang dapat diambil dan digunakan oleh konstruktor. -
Secara opsional, buat pemroses untuk peristiwa yang mungkin dihasilkan oleh tampilan yang dimuat Anda. Contohnya adalah
metode pemroses 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 membuat kueri untuk kontennya jika diperlukan. -
Atau, ganti
onDraw()
danonMeasure()
. Ini biasanya tidak diperlukan saat memperluasLayout
, karena tata letak memiliki perilaku default yang kemungkinan akan berfungsi dengan baik. -
Secara opsional, ganti metode
on
lain, sepertionKeyDown()
, misalnya untuk memilih nilai default tertentu dari daftar pop-up kotak kombinasi saat tombol tertentu diketuk.
Terdapat beberapa keuntungan dalam menggunakan Layout
sebagai dasar kontrol kustom, termasuk yang berikut ini:
- Anda dapat menentukan tata letak menggunakan file XML deklaratif, sama seperti pada layar aktivitas, atau Anda bisa membuat tampilan secara terprogram dan menyusunnya ke dalam tata letak dari kode Anda.
-
Metode
onDraw()
danonMeasure()
, serta sebagian besar metodeon
lainnya, 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 diubah. 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 sempurna, dan API untuk melakukan ini mungkin berubah, tetapi ini menunjukkan prinsipnya.
Jika Anda belum melakukannya, impor contoh NotePad ke Android Studio atau lihat
sumbernya menggunakan link yang disediakan. Secara khusus, lihat definisi LinedEditText
dalam
file
NoteEditor.java
.
Berikut beberapa hal yang perlu diketahui dalam file ini:
-
Definisi
Class ditentukan dengan baris berikut:
public static class LinedEditText extends EditText
LinedEditText
didefinisikan sebagai class dalam di dalam aktivitasNoteEditor
, tetapi bersifat publik sehingga dapat diakses sebagaiNoteEditor.LinedEditText
dari luar classNoteEditor
.Selain itu,
LinedEditText
adalahstatic
, yang berarti kode tersebut tidak menghasilkan apa yang disebut "metode sintetis" yang memungkinkannya mengakses data dari class induk. Ini berarti kode berperilaku sebagai class terpisah, bukan sesuatu yang sangat terkait denganNoteEditor
. Cara ini lebih sederhana untuk membuat inner class jika class tersebut tidak memerlukan akses ke state dari outer class. Hal ini membuat class yang dihasilkan tetap kecil dan memungkinkannya digunakan dengan mudah dari class lain.LinedEditText
memperluasEditText
, yang merupakan tampilan yang akan disesuaikan dalam kasus ini. Setelah Anda selesai, class baru dapat menggantikan tampilanEditText
normal. -
Inisialisasi class
Seperti biasa, super dipanggil terlebih dahulu. Ini bukan konstruktor default, tetapi konstruktor berparameter.
EditText
dibuat dengan parameter ini saat di-inflate dari file tata letak XML. Dengan demikian, konstruktor perlu mengambilnya 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 Anda sendiri.Untuk contoh ini, penggantian metode
onDraw()
memungkinkan Anda melukis 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 kode tersebut di akhir setelah Anda menggambar garis yang ingin disertakan. -
Komponen kustom
Anda sekarang memiliki komponen kustom, tetapi bagaimana cara menggunakannya? Dalam contoh NotePad, komponen kustom digunakan langsung dari tata letak deklaratif, jadi lihat
note_editor.xml
di 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 dalam XML, dan class ditetapkan menggunakan paket lengkap. Class dalam yang Anda tentukan direferensikan menggunakan notasi
NoteEditor$LinedEditText
, yang merupakan cara standar untuk merujuk ke class dalam bahasa pemrograman Java.Jika komponen tampilan kustom Anda tidak didefinisikan sebagai inner class, 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
LinedEditText
kini merupakan file class terpisah. Jika class disusun bertingkat di classNoteEditor
, teknik ini tidak akan berfungsi.Atribut dan parameter lain dalam definisi adalah atribut dan parameter yang diteruskan ke konstruktor komponen kustom, kemudian diteruskan ke konstruktor
EditText
, sehingga merupakan parameter yang sama dengan yang Anda gunakan untuk tampilanEditText
. Anda juga dapat menambahkan parameter sendiri.
Membuat komponen kustom hanya serumit yang Anda perlukan.
Komponen yang lebih canggih dapat mengganti lebih banyak metode on
dan memperkenalkan
metode bantuannya sendiri, yang secara substansial menyesuaikan properti dan perilakunya. Satu-satunya batasan adalah imajinasi Anda
dan apa yang Anda perlu lakukan komponennya.