Tata letak dalam View

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

Tata letak menentukan struktur untuk antarmuka pengguna di aplikasi Anda, seperti dalam aktivitas. Semua elemen dalam tata letak dibuat menggunakan hierarki objek View dan ViewGroup. View biasanya menggambar sesuatu yang dapat dilihat dan berinteraksi dengan pengguna. ViewGroup adalah penampung tidak terlihat yang menentukan struktur tata letak untuk View dan objek ViewGroup lainnya, seperti yang ditunjukkan pada gambar 1.

Gambar 1. Ilustrasi hierarki tampilan, yang menentukan tata letak UI.

Objek View sering disebut widget dan dapat menjadi salah satu dari banyak subclass, seperti Button atau TextView. Objek ViewGroup biasanya disebut tata letak dan dapat berupa salah satu dari banyak jenis yang memberikan struktur tata letak berbeda, seperti LinearLayout atau ConstraintLayout.

Anda dapat mendeklarasikan tata letak dengan dua cara:

  • Deklarasikan elemen UI dalam XML. Android menyediakan kosakata XML sederhana yang sesuai dengan class dan subclass View, seperti untuk widget dan tata letak. Anda juga dapat menggunakan Layout Editor Android Studio untuk membuat tata letak XML menggunakan antarmuka tarik lalu lepas.

  • Buat instance elemen tata letak saat runtime. Aplikasi Anda dapat membuat objek View dan ViewGroup serta memanipulasi propertinya secara terprogram.

Dengan mendeklarasikan UI dalam XML, Anda dapat memisahkan presentasi aplikasi dari kode yang mengontrol perilakunya. Penggunaan file XML juga akan mempermudah penyediaan tata letak yang berbeda untuk berbagai ukuran dan orientasi layar. Hal ini dibahas lebih lanjut di Mendukung berbagai ukuran layar.

Framework Android memberi Anda fleksibilitas untuk menggunakan salah satu atau kedua metode ini untuk membuat UI aplikasi Anda. Misalnya, Anda dapat mendeklarasikan tata letak default aplikasi pada XML, lalu mengubah tata letak tersebut saat runtime.

Menulis XML

Dengan menggunakan kosakata XML Android, Anda dapat dengan cepat mendesain tata letak UI dan elemen layar yang ada di dalamnya, sama seperti saat membuat halaman web dalam HTML dengan serangkaian elemen bertingkat.

Setiap file tata letak harus berisi persis satu elemen root, yang harus berupa objek View atau ViewGroup. Setelah menentukan elemen root, Anda dapat menambahkan objek tata letak atau widget tambahan sebagai elemen turunan untuk mem-build hierarki View yang menentukan tata letak secara bertahap. Misalnya, berikut adalah tata letak XML yang menggunakan LinearLayout vertikal untuk menyimpan TextView dan Button:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" />
</LinearLayout>

Setelah mendeklarasikan tata letak dalam XML, simpan file dengan ekstensi .xml di direktori res/layout/ project Android Anda agar dapat dikompilasi dengan benar.

Untuk mengetahui informasi selengkapnya tentang sintaksis file XML tata letak, lihat Resource tata letak.

Memuat resource XML

Saat mengompilasi aplikasi, masing-masing file tata letak XML akan dikompilasikan menjadi resource View. Muat resource tata letak di implementasi callback Activity.onCreate() aplikasi Anda. Lakukan dengan memanggil setContentView(), dengan meneruskan referensi ke resource tata letak dalam bentuk: R.layout.layout_file_name. Misalnya, jika tata letak XML Anda disimpan sebagai main_layout.xml, muat tata letak tersebut untuk Activity seperti berikut:

Kotlin

fun onCreate(savedInstanceState: Bundle) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_layout)
}

Java

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
}

Framework Android memanggil metode callback onCreate() di Activity Anda saat Activity diluncurkan. Untuk informasi selengkapnya tentang siklus proses aktivitas, lihat Pengantar aktivitas.

Atribut

Setiap objek View dan ViewGroup mendukung berbagai atribut XML-nya sendiri. Beberapa atribut bersifat khusus untuk objek View. Misalnya, TextView mendukung atribut textSize. Namun, atribut ini juga diwarisi oleh objek View yang memperluas class ini. Sebagian bersifat umum untuk semua objek View, karena diwarisi dari class View root, seperti atribut id. Atribut lain dianggap sebagai parameter tata letak, yaitu atribut yang mendeskripsikan orientasi tata letak tertentu dari objek View, seperti yang ditentukan oleh objek ViewGroup induk objek tersebut.

ID

Setiap objek View dapat memiliki ID bilangan bulat yang terkait dengannya untuk mengidentifikasi View secara unik dalam hierarki. Saat aplikasi dikompilasi, ID ini direferensikan sebagai bilangan bulat, tetapi ID tersebut biasanya ditetapkan dalam file XML tata letak sebagai string dalam atribut id. Ini adalah atribut XML yang umum untuk semua objek View, dan ditentukan oleh class View. Anda sering menggunakannya. Sintaksis untuk ID di dalam tag XML adalah sebagai berikut:

android:id="@+id/my_button"

Simbol at (@) di awal string menunjukkan bahwa Parser XML akan mengurai dan meluaskan sisa string ID dan mengidentifikasinya sebagai resource ID. Simbol plus (+) berarti ini adalah nama resource baru yang harus dibuat dan ditambahkan ke resource Anda dalam file R.java.

Framework Android menawarkan banyak resource ID lainnya. Saat mereferensikan ID resource Android, Anda tidak memerlukan simbol plus, tetapi harus menambahkan namespace paket android seperti berikut:

android:id="@android:id/empty"

Namespace paket android menunjukkan bahwa Anda mereferensikan ID dari class resource android.R, bukan class resource lokal.

Untuk membuat tampilan dan mereferensikannya dari aplikasi, Anda dapat menggunakan pola umum sebagai berikut:

  1. Tentukan tampilan dalam file tata letak dan tetapkan ID unik, seperti dalam contoh berikut:
    <Button android:id="@+id/my_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/my_button_text"/>
    
  2. Buat instance objek tampilan dan ambil dari tata letak, biasanya dalam metode onCreate(), seperti ditunjukkan dalam contoh berikut:

    Kotlin

    val myButton: Button = findViewById(R.id.my_button)
    

    Java

    Button myButton = (Button) findViewById(R.id.my_button);
    

Menentukan ID untuk objek tampilan adalah hal penting saat membuat RelativeLayout. Dalam tata letak relatif, tampilan yang setara dapat menentukan tata letak secara relatif terhadap tampilan seinduk lainnya, yang dirujuk oleh ID unik.

ID tidak harus unik di seluruh hierarki, tetapi harus unik di dalam bagian hierarki yang Anda telusuri. Sering kali bisa berupa seluruh pohon, jadi sebaiknya buat unik jika memungkinkan.

Parameter tata letak

Atribut tata letak XML bernama layout_something menentukan parameter tata letak untuk View yang sesuai untuk ViewGroup tempatnya berada.

Setiap class ViewGroup menerapkan class bertingkat yang memperluas ViewGroup.LayoutParams. Subclass ini berisi jenis properti yang mendefinisikan ukuran dan posisi setiap tampilan turunan, sebagaimana mestinya untuk grup tampilan. Seperti yang ditunjukkan dalam gambar 2, kelompok tampilan induk menentukan parameter tata letak untuk setiap tampilan turunan, termasuk kelompok tampilan turunan.

Gambar 2. Visualisasi hierarki tampilan dengan parameter tata letak yang dikaitkan dengan setiap tampilan.

Setiap subclass LayoutParams memiliki sintaksisnya sendiri untuk menetapkan nilai. Setiap elemen turunan harus menetapkan LayoutParams yang sesuai untuk induknya, meskipun elemen tersebut juga dapat menentukan LayoutParams yang berbeda untuk turunannya sendiri.

Semua grup tampilan berisi lebar dan tinggi, dengan menggunakan layout_width dan layout_height, dan setiap tampilan diperlukan untuk mendefinisikannya. Banyak LayoutParams yang menyertakan margin dan batas opsional.

Anda dapat menentukan lebar dan tinggi dengan ukuran yang tepat, tetapi Anda mungkin tidak ingin sering melakukannya. Sering kali, Anda akan menggunakan salah satu konstanta ini untuk menyetel lebar atau tinggi:

  • wrap_content: memberi tahu tampilan Anda agar menyesuaikan ukurannya sendiri dengan dimensi yang dibutuhkan oleh kontennya.
  • match_parent: memberi tahu tampilan Anda agar menjadi sebesar yang diizinkan oleh kelompok tampilan induknya.

Secara umum, kami tidak merekomendasikan penetapan lebar dan tinggi tata letak menggunakan satuan absolut seperti piksel. Pendekatan yang lebih baik adalah menggunakan ukuran relatif, seperti satuan piksel kepadatan mandiri (dp), wrap_content, atau match_parent, karena membantu aplikasi Anda ditampilkan dengan benar di berbagai ukuran layar perangkat. Jenis pengukuran yang diterima ditentukan di Resource tata letak.

Posisi tata letak

Sebuah tampilan memiliki geometri persegi panjang. Bidang ini memiliki lokasi, yang dinyatakan sebagai pasangan koordinat kiri dan atas, serta dua dimensi, yang dinyatakan sebagai lebar dan tinggi. Satuan untuk lokasi dan dimensi adalah piksel.

Anda dapat mengambil lokasi tampilan dengan memanggil metode getLeft() dan getTop(). Metode pertama menampilkan koordinat kiri (x) persegi panjang yang merepresentasikan tampilan. Kode kedua menampilkan koordinat (y) atas persegi panjang yang mewakili tampilan. Metode ini menampilkan lokasi tampilan relatif terhadap induknya. Misalnya, jika getLeft() menampilkan 20, berarti tampilan terletak 20 piksel di sebelah kanan tepi kiri induk langsungnya.

Selain itu, ada metode praktis untuk menghindari komputasi yang tidak perlu: yaitu getRight() dan getBottom(). Metode ini menampilkan koordinat tepi kanan dan bawah persegi panjang yang merepresentasikan tampilan. Misalnya, memanggil getRight() mirip dengan komputasi berikut: getLeft() + getWidth().

Ukuran, padding, dan margin

Ukuran tampilan dinyatakan dengan lebar dan tinggi. Tampilan memiliki dua pasang nilai lebar dan tinggi.

Pasangan pertama dikenal sebagai lebar terukur dan tinggi terukur. Dimensi ini menentukan seberapa besar tampilan yang diinginkan dalam induknya. Anda dapat memperoleh dimensi terukur dengan memanggil getMeasuredWidth() dan getMeasuredHeight().

Pasangan kedua disebut sebagai lebar dan tinggi, atau terkadang lebar gambar dan tinggi gambar. Dimensi ini menentukan ukuran tampilan sebenarnya di layar, pada waktu menggambar dan setelah tata letak. Nilai ini mungkin, tetapi tidak harus, berbeda dengan lebar dan tinggi terukur. Anda bisa memperoleh lebar dan tinggi dengan memanggil getWidth() dan getHeight().

Untuk mengukur dimensinya, tampilan akan memperhitungkan pengisinya. Padding dinyatakan dalam piksel untuk bagian kiri, atas, kanan, dan bawah tampilan. Anda dapat menggunakan padding untuk mengimbangi konten tampilan dengan jumlah piksel tertentu. Misalnya, padding kiri sebanyak dua mendorong konten tampilan dua piksel ke kanan dari tepi kiri. Anda dapat menyetel padding menggunakan metode setPadding(int, int, int, int) dan membuat kuerinya dengan memanggil getPaddingLeft(), getPaddingTop(), getPaddingRight(), dan getPaddingBottom().

Meskipun dapat mendefinisikan padding, tampilan tidak mendukung margin. Namun, grup tampilan mendukung margin. Lihat ViewGroup dan ViewGroup.MarginLayoutParams untuk mengetahui informasi selengkapnya.

Untuk mengetahui informasi selengkapnya tentang dimensi, lihat Dimensi.

Selain menyetel margin dan padding secara terprogram, Anda juga dapat menetapkannya dalam tata letak XML, seperti yang ditunjukkan dalam contoh berikut:

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical" >
      <TextView android:id="@+id/text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="16dp"
                android:padding="8dp"
                android:text="Hello, I am a TextView" />
      <Button android:id="@+id/button"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_marginTop="16dp"
              android:paddingBottom="4dp"
              android:paddingEnd="8dp"
              android:paddingStart="8dp"
              android:paddingTop="4dp"
              android:text="Hello, I am a Button" />
  </LinearLayout>
  

Contoh sebelumnya menunjukkan margin dan padding yang diterapkan. TextView memiliki margin dan padding seragam yang diterapkan di sekelilingnya, dan Button menunjukkan cara menerapkannya secara terpisah ke tepi yang berbeda.

Tata letak umum

Setiap subclass dari class ViewGroup menyediakan cara unik untuk menampilkan tampilan yang Anda tempatkan di dalamnya. Jenis tata letak yang paling fleksibel, dan satu-satunya yang menyediakan alat terbaik untuk menjaga hierarki tata letak Anda tetap dangkal, adalah ConstraintLayout.

Berikut ini adalah beberapa jenis tata letak umum yang dibangun ke dalam platform Android.

Membuat tata letak linear

Mengatur turunannya ke dalam satu baris horizontal atau vertikal dan membuat scrollbar jika panjang jendela melebihi panjang layar.

Membuat aplikasi web di WebView

Menampilkan halaman web.

Membuat daftar dinamis

Jika konten untuk tata letak bersifat dinamis atau tidak ditentukan sebelumnya, Anda dapat menggunakan RecyclerView atau subclass dari AdapterView. RecyclerView umumnya adalah opsi yang lebih baik karena menggunakan memori secara lebih efisien daripada AdapterView.

Tata letak umum yang dapat dilakukan dengan RecyclerView dan AdapterView mencakup hal berikut:

Daftar

Menampilkan daftar kolom tunggal yang bergulir.

Petak

Menampilkan petak kolom dan baris yang bergulir.

RecyclerView menawarkan lebih banyak kemungkinan dan opsi untuk membuat pengelola tata letak kustom.

Mengisi tampilan adaptor dengan data

Anda dapat mengisi AdapterView seperti ListView atau GridView dengan mengikat instance AdapterView ke Adapter, yang mengambil data dari sumber eksternal dan membuat View yang mewakili setiap entri data.

Android menyediakan beberapa subclass Adapter yang berguna untuk mengambil berbagai jenis data dan membuat tampilan untuk AdapterView. Dua adapter yang paling umum adalah:

ArrayAdapter
Gunakan adaptor ini bila sumber data berupa array. Secara default, ArrayAdapter akan membuat tampilan untuk setiap item array dengan memanggil toString() pada setiap item dan menempatkan konten dalam TextView.

Misalnya, jika Anda memiliki array string yang ingin ditampilkan dalam ListView, lakukan inisialisasi ArrayAdapter baru menggunakan konstruktor untuk menetapkan tata letak setiap string dan array string:

Kotlin

    val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray)
    

Java

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_1, myStringArray);
    

Argumen untuk konstruktor ini adalah sebagai berikut:

  • Aplikasi Anda Context
  • Tata letak yang berisi TextView untuk setiap string dalam array
  • Array string

Lalu, panggil setAdapter() di ListView Anda:

Kotlin

    val listView: ListView = findViewById(R.id.listview)
    listView.adapter = adapter
    

Java

    ListView listView = (ListView) findViewById(R.id.listview);
    listView.setAdapter(adapter);
    

Untuk menyesuaikan tampilan setiap item, Anda dapat mengganti metode toString() untuk objek dalam array Anda. Atau, untuk membuat tampilan bagi setiap item yang bukan TextView—misalnya, jika Anda menginginkan ImageView untuk setiap item array—perluas class ArrayAdapter dan ganti getView() untuk menampilkan jenis tampilan yang Anda inginkan untuk setiap item.

SimpleCursorAdapter
Gunakan adaptor ini jika data Anda berasal dari Cursor. Saat menggunakan SimpleCursorAdapter, tentukan tata letak yang akan digunakan untuk setiap baris dalam Cursor dan kolom mana di Cursor yang ingin disisipkan ke dalam tampilan tata letak yang Anda inginkan. Misalnya, jika ingin membuat daftar nama orang dan nomor telepon, Anda dapat melakukan kueri yang menampilkan Cursor yang berisi satu baris untuk setiap orang serta kolom untuk nama dan nomor. Selanjutnya, buat array string yang menentukan kolom dari Cursor yang Anda inginkan dalam tata letak untuk setiap hasil dan array bilangan bulat yang menentukan tampilan terkait yang harus ditempatkan oleh setiap kolom:

Kotlin

    val fromColumns = arrayOf(ContactsContract.Data.DISPLAY_NAME,
                              ContactsContract.CommonDataKinds.Phone.NUMBER)
    val toViews = intArrayOf(R.id.display_name, R.id.phone_number)
    

Java

    String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
                            ContactsContract.CommonDataKinds.Phone.NUMBER};
    int[] toViews = {R.id.display_name, R.id.phone_number};
    

Saat Anda membuat instance SimpleCursorAdapter, teruskan tata letak yang akan digunakan untuk setiap hasil, Cursor yang berisi hasil tersebut, dan kedua array ini:

Kotlin

    val adapter = SimpleCursorAdapter(this,
            R.layout.person_name_and_number, cursor, fromColumns, toViews, 0)
    val listView = getListView()
    listView.adapter = adapter
    

Java

    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
            R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
    ListView listView = getListView();
    listView.setAdapter(adapter);
    

SimpleCursorAdapter kemudian membuat tampilan untuk setiap baris dalam Cursor menggunakan tata letak yang disediakan dengan memasukkan setiap item fromColumns ke dalam tampilan toViews yang sesuai.

Jika selama masa pakai aplikasi Anda mengubah data pokok yang dibaca oleh adaptor, panggil notifyDataSetChanged(). Hal ini akan memberi tahu tampilan terlampir bahwa data telah diubah dan akan dimuat ulang dengan sendirinya.

Menangani peristiwa klik

Anda dapat merespons peristiwa klik pada setiap item dalam AdapterView dengan mengimplementasikan antarmuka AdapterView.OnItemClickListener. Contoh:

Kotlin

listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
    // Do something in response to the click.
}

Java

// Create a message handling object as an anonymous class.
private OnItemClickListener messageClickedHandler = new OnItemClickListener() {
    public void onItemClick(AdapterView parent, View v, int position, long id) {
        // Do something in response to the click.
    }
};

listView.setOnItemClickListener(messageClickedHandler);

Referensi tambahan

Lihat cara tata letak digunakan dalam aplikasi demo Sunflower di GitHub.