Android menawarkan model canggih dan andal yang terbagi menjadi komponen terpisah untuk mem-build UI,
berdasarkan class tata letak dasar: View
dan
ViewGroup
. Sebagai permulaan, platform ini mencakup berbagai subclass
View dan ViewGroup bawaan—masing-masing disebut widget dan tata letak—
yang dapat digunakan untuk mem-build 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 Objek Tata Letak Umum.
Jika tidak ada widget atau tata letak bawaan yang memenuhi kebutuhan, Anda dapat membuat subclass View sendiri. Jika Anda hanya perlu membuat sedikit penyesuaian pada widget atau tata letak yang ada, cukup buat subclass widget atau tata letak dan ganti metodenya.
Pembuatan 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 hal yang dapat dilakukan dengan tampilan kustom:
- Anda dapat membuat jenis View yang sepenuhnya dirender secara kustom, misalnya tombol "kontrol volume" yang dirender menggunakan grafis 2D, dan yang menyerupai kontrol elektronik analog.
- Anda dapat menggabungkan sekumpulan komponen View menjadi 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 masing-masing panel, tempat Anda dapat menetapkan kembali letak setiap item dalam setiap daftar), dan sebagainya.
- Anda dapat mengganti cara komponen EditText dirender di layar ( Tutorial 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 di bawah ini menjelaskan cara membuat View kustom dan menggunakannya di aplikasi.
Untuk mengetahui informasi referensi yang mendetail, buka class View
.
Pendekatan Dasar
Berikut ringkasan umum tentang hal yang perlu diketahui untuk memulai pembuatan 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, class ekstensi baru dapat digunakan sebagai pengganti tampilan yang menjadi dasarnya.
Tips: Class ekstensi dapat didefinisikan sebagai class dalam di dalam aktivitas yang menggunakannya. Ini berguna karena class ekstensi mengontrol akses ke class dalam, tetapi tidak diperlukan (mungkin Anda ingin membuat View publik baru untuk penggunaan yang lebih luas di aplikasi).
Komponen yang Disesuaikan Sepenuhnya
Komponen yang disesuaikan sepenuhnya dapat digunakan untuk membuat komponen grafis yang muncul sesuai keinginan Anda. Mungkin VU meter grafis yang tampak seperti pengukur analog lama, atau tampilan teks untuk menyanyikan lagu, dengan bola yang bergerak mengikuti kata sehingga Anda dapat bernyanyi bersama mesin karaoke. Apa pun itu, Anda memerlukan sesuatu yang tidak dapat dilakukan oleh komponen bawaan, bagaimana pun Anda menggabungkannya.
Untungnya, Anda dapat dengan mudah membuat komponen yang terlihat dan berperilaku sesuai keinginan, yang mungkin hanya dibatasi oleh imajinasi Anda, ukuran layar, dan daya pemrosesan yang tersedia (ingat bahwa pada akhirnya aplikasi mungkin harus dijalankan pada perangkat dengan daya yang jauh lebih sedikit dibandingkan workstation desktop).
Untuk membuat komponen yang disesuaikan sepenuhnya:
-
Tentu saja, tampilan paling umum yang dapat diperluas adalah
View
, jadi biasanya Anda akan memulai dengan memperluasnya untuk membuat komponen super baru. - Anda dapat menyediakan konstruktor yang mampu mengambil atribut dan parameter dari XML. Anda juga dapat memakai atribut dan parameter sendiri (mungkin warna dan rentang VU meter, atau lebar dan peredaman jarum, dan sebagainya.)
- Anda mungkin ingin membuat pemroses peristiwa, pengakses properti, dan pengubah sendiri, dan mungkin juga 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 akan melakukan apa pun, danonMeasure()
default akan selalu menetapkan ukuran 100x100—yang mungkin bukan ukuran yang Anda inginkan. -
Metode
on...
lain juga dapat diganti sesuai kebutuhan.
Memperluas onDraw()
dan onMeasure()
Metode onDraw()
menghadirkan Canvas
tempat Anda dapat mengimplementasikan apa pun yang diinginkan: grafis 2D, komponen standar
atau kustom lain, teks bergaya, atau apa pun yang Anda inginkan.
Catatan:
Ini tidak berlaku untuk grafis 3D. Jika ingin
menggunakan grafis 3D, Anda harus memperluas SurfaceView
dan bukan View, dan menggambar dari thread terpisah. Buka
contoh GLSurfaceViewActivity
untuk mengetahui detailnya.
onMeasure()
sedikit lebih terlibat. onMeasure()
merupakan bagian penting dari perenderan kontrak antara komponen Anda dan
container-nya. onMeasure()
harus diganti agar dapat melaporkan pengukuran
bagian-bagian yang terdapat di dalamnya secara efisien dan akurat. Ini dibuat
sedikit lebih kompleks dengan persyaratan batas dari induk
(yang diteruskan ke metode onMeasure()
) dan dengan
persyaratan untuk memanggil metode setMeasuredDimension()
dengan
lebar dan tinggi yang diukur setelah selesai dihitung. Jika gagal
memanggil metode ini dari metode onMeasure()
yang telah diganti, hasilnya
akan menjadi pengecualian pada waktu pengukuran.
Pada level yang tinggi, implementasi onMeasure()
akan terlihat seperti ini:
-
Metode
onMeasure()
yang telah diganti dipanggil dengan spesifikasi ukuran lebar dan tinggi (parameterwidthMeasureSpec
danheightMeasureSpec
, keduanya merupakan kode bilangan bulat yang mewakili dimensi) yang harus diperlakukan sebagai persyaratan untuk batasan terhadap pengukuran lebar dan tinggi yang harus dihasilkan. Referensi lengkap tentang jenis batasan yang dapat dijadikan persyaratan oleh spesifikasi ini dapat ditemukan di dokumentasi referensi dalamView.onMeasure(int, int)
(dokumentasi referensi ini juga menjelaskan keseluruhan operasi pengukuran dengan baik). -
Metode
onMeasure()
komponen harus menghitung lebar dan tinggi pengukuran yang diperlukan untuk merender komponen. Metode ini harus mencoba tetap dalam spesifikasi yang diteruskan, meskipun dapat memilih untuk 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 berbeda). -
Setelah lebar dan tinggi dihitung, metode
setMeasuredDimension(int width, int height)
harus dipanggil dengan pengukuran yang telah dihitung. Jika gagal melakukannya, pengecualian akan dilempar.
Berikut ringkasan beberapa metode standar lainnya yang dipanggil framework pada tampilan:
Kategori | Metode | Deskripsi |
---|---|---|
Kreasi | Konstruktor | Ada formulir konstruktor yang dipanggil saat tampilan dibuat dari kode dan formulir konstruktor yang dipanggil saat tampilan di-inflate dari file tata letak. Formulir kedua harus mengurai dan menerapkan atribut apa pun yang ditetapkan dalam file tata letak. |
|
Dipanggil setelah tampilan dan semua turunannya telah 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 telah berubah. | |
Gambar |
|
Dipanggil saat tampilan harus merender kontennya. |
Pemrosesan peristiwa |
|
Dipanggil saat peristiwa tombol baru 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 dipasang ke jendela. |
|
Dipanggil saat tampilan dilepas dari jendelanya. | |
|
Dipanggil saat visibilitas jendela yang berisi tampilan telah berubah. |
Kontrol Compound
Jika Anda tidak ingin membuat komponen yang disesuaikan sepenuhnya, tetapi ingin menyatukan komponen yang dapat digunakan kembali yang terdiri atas sekumpulan kontrol yang ada, maka membuat Komponen Compound (atau Kontrol Compound) mungkin cocok untuk Anda. 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 dianggap sebagai kombinasi dari satu baris kolom EditText dan tombol yang berdekatan, dengan PopupList terpasang. Jika menekan tombol tersebut dan memilih sesuatu dari daftar, pilihan Anda akan mengisi kolom EditText, tetapi pengguna juga dapat mengetik sesuatu secara langsung ke kolom EditText jika menginginkannya.
Di Android, sebenarnya ada dua View lain yang tersedia untuk melakukannya:
Spinner
dan
AutoCompleteTextView
, tetapi
terlepas dari itu, konsep Kotak Kombinasi merupakan contoh yang mudah
dipahami.
Untuk membuat komponen compound:
- Titik awal yang umum adalah Layout, jadi buat class yang memperluas Layout. Mungkin dalam kasus Kotak kombinasi, kita dapat menggunakan LinearLayout dengan orientasi horizontal. Ingat bahwa tata letak lain dapat disarangkan di dalamnya, sehingga komponen compound dapat menjadi kompleks dan terstruktur secara bebas. Perlu diketahui bahwa seperti Activity, Anda dapat menggunakan pendekatan deklaratif (berbasis XML) untuk membuat komponen yang terdapat di dalamnya, atau menyarangkannya secara terprogram dari kode.
- Dalam konstruktor untuk class baru, ambil parameter apa pun yang diharapkan superclass, lalu teruskan parameter tersebut melalui konstruktor superclass terlebih dahulu. Selanjutnya Anda dapat menyiapkan tampilan lain untuk digunakan dalam komponen baru; ini adalah tempat Anda akan membuat kolom EditText dan PopupList. Perlu diketahui bahwa Anda juga dapat memperkenalkan atribut dan parameter sendiri ke XML yang dapat diambil dan digunakan oleh konstruktor.
- Anda juga dapat membuat pemroses untuk peristiwa yang dapat dihasilkan oleh tampilan yang ada di dalamnya, misalnya, metode pemroses untuk Pemroses Klik Item Daftar agar memperbarui konten EditText jika pilihan daftar dibuat.
- Anda juga dapat membuat properti sendiri dengan pengakses dan pengubah, misalnya, izinkan nilai EditText ditetapkan di awal dalam komponen dan mengajukan kueri untuk kontennya saat diperlukan.
-
Dalam kasus perluasan Layout, Anda tidak perlu mengganti
metode
onDraw()
danonMeasure()
karena tata letak akan memiliki perilaku default yang kemungkinan akan berfungsi dengan baik. Namun, Anda masih dapat menggantikannya jika perlu. -
Anda dapat mengganti metode
on...
lain, sepertionKeyDown()
, untuk memilih nilai default tertentu dari daftar pop-up kotak kombinasi saat tombol tertentu ditekan.
Ringkasnya, penggunaan Layout sebagai dasar untuk Kontrol Kustom memiliki beberapa keuntungan, termasuk:
- Seperti pada layar aktivitas, Anda dapat menentukan tata letak menggunakan file XML deklaratif, atau membuat tampilan secara terprogram dan menyarangkannya ke tata letak dari kode.
-
Metode
onDraw()
danonMeasure()
(serta sebagian besar metodeon...
lainnya) kemungkinan akan memiliki perilaku yang sesuai, sehingga Anda tidak perlu menggantinya. - Pada akhirnya, Anda dapat dengan cepat membuat tampilan compound yang kompleks secara bebas dan menggunakannya kembali seolah tampilan tersebut merupakan komponen tunggal.
Mengubah Jenis View yang Ada
Ada opsi yang lebih mudah untuk membuat View kustom, yang bermanfaat dalam situasi tertentu. Jika ada komponen yang sudah sangat mirip dengan yang diinginkan, Anda hanya perlu memperluas komponen tersebut dan mengganti perilaku yang ingin diubah. Anda dapat melakukan semua hal yang biasanya dilakukan dengan komponen yang disesuaikan sepenuhnya, tetapi dengan mulai menggunakan class khusus dalam hierarki View. Anda juga bisa mendapatkan banyak perilaku gratis yang kemungkinan melakukan hal persis seperti yang diinginkan.
Misalnya, aplikasi NotePad menunjukkan banyak aspek penggunaan platform Android. Di antaranya adalah memperluas View EditText untuk membuat notepad bergaris. Ini bukan contoh yang ideal, dan API untuk melakukannya mungkin berubah, tetapi contoh ini menunjukkan prinsipnya.
Impor contoh NotePad ke Android Studio (atau
cukup lihat sumber menggunakan link yang tersedia) jika Anda belum melakukannya. Secara khusus, perhatikan 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 EditText
-
LinedEditText
didefinisikan sebagai class dalam di dalam aktivitasNoteEditor
, tetapi bersifat publik sehingga dapat diakses sebagaiNoteEditor.LinedEditText
dari luar classNoteEditor
jika diinginkan. -
Class ini
static
, artinya tidak menghasilkan "metode sintesis" yang memungkinkannya mengakses data dari class induk. Artinya, class ini benar-benar berperilaku sebagai class terpisah, bukan class 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, menjaga agar class yang dihasilkan tetap kecil, dan memungkinkannya digunakan dengan mudah dari class lain. -
Class ini memperluas
EditText
, yakni View yang telah dipilih untuk disesuaikan dalam kasus ini. Setelah selesai, class baru akan dapat menggantikan tampilanEditText
normal.
-
-
Inisialisasi Class
Seperti biasa, super dipanggil terlebih dahulu. Selain itu, ini bukan konstruktor default, tetapi konstruktor berparameter. EditText dibuat dengan parameter ini saat di-inflate dari file tata letak XML, karena itu, konstruktor juga harus mengambil dan meneruskannya ke konstruktor superclass.
-
Metode yang Diganti
Contoh ini hanya mengganti satu metode,
onDraw()
, tetapi Anda mungkin harus mengganti metode lain saat membuat komponen kustom sendiri.Untuk contoh ini, penggantian metode
onDraw()
memungkinkan kita menggambar garis biru di kanvas tampilanEditText
(kanvas diteruskan ke metodeonDraw()
yang diganti). Metode super.onDraw() dipanggil sebelum metode berakhir. Metode superclass harus dipanggil, dan dalam hal ini, kita melakukannya di akhir setelah menggambar garis yang ingin disertakan. -
Menggunakan Komponen Kustom
Sekarang kita memiliki komponen kustom, tetapi bagaimana cara menggunakannya? Dalam contoh NotePad, komponen kustom digunakan secara langsung dari tata letak deklaratif, jadi lihat
note_editor.xml
dalam folder res/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 ditetapkan menggunakan paket lengkap. Perlu diketahui juga bahwa
class dalam yang ditetapkan direferensikan menggunakan
notasi
NoteEditor$LinedEditText
, yang merupakan cara standar dalam bahasa pemrograman Java untuk mereferensikan class dalam.Jika komponen View kustom tidak didefinisikan sebagai class dalam, maka sebagai gantinya, Anda dapat mendeklarasikan komponen View 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 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, kemudian diteruskan melalui konstruktor EditText, sehingga merupakan parameter yang sama yang akan digunakan untuk tampilan EditText. Perlu diketahui bahwa Anda juga dapat menambahkan parameter sendiri. Hal ini akan dibahas lagi di bawah.
-
Komponen kustom dibuat sebagai tampilan umum di XML, dan
class ditetapkan menggunakan paket lengkap. Perlu diketahui juga bahwa
class dalam yang ditetapkan direferensikan menggunakan
notasi
Itu saja yang dapat disampaikan. Ini memang kasus yang sederhana, tetapi itulah tujuan utamanya—proses pembuatan komponen kustom memang sederhana.
Komponen yang lebih rumit dapat menggantikan lebih banyak metode on...
dan
memperkenalkan beberapa metode helper-nya sendiri, yang secara substansial menyesuaikan properti dan
perilakunya. Batasannya hanyalah imajinasi Anda dan hal yang menurut Anda harus dilakukan
komponen.