Batasan dan urutan pengubah

Di Compose, Anda dapat menggabungkan beberapa pengubah untuk mengubah tampilan dan nuansa composable. Rantai pengubah ini dapat memengaruhi batasan yang diteruskan ke composable, yang menentukan batas lebar dan tinggi.

Halaman ini menjelaskan pengaruh pengubah berantai terhadap batasan dan, pada gilirannya, pengukuran dan penempatan composable.

Pengubah di hierarki UI

Untuk memahami pengaruh pengubah satu sama lain, sebaiknya visualisasikan tampilannya di hierarki UI, yang dibuat selama fase komposisi. Untuk mengetahui informasi selengkapnya, lihat bagian Komposisi.

Di hierarki UI, Anda dapat memvisualisasikan pengubah sebagai node wrapper untuk node tata letak:

Kode untuk composable dan pengubah, serta representasi visualnya sebagai hierarki UI.
Gambar 1. Pengubah yang menggabungkan node tata letak di hierarki UI.

Menambahkan lebih dari satu pengubah ke composable akan membuat rantai pengubah. Saat Anda menggabungkan beberapa pengubah, setiap node pengubah menggabungkan sisa rantai dan node tata letak di dalamnya. Misalnya, saat Anda menggabungkan pengubah clip dan size, node pengubah clip akan menggabungkan node pengubah size, yang kemudian menggabungkan node tata letak Image.

Pada fase tata letak, algoritma yang menelusuri hierarki tetap sama, tetapi setiap node pengubah juga dikunjungi. Dengan cara ini, pengubah dapat mengubah persyaratan ukuran dan penempatan pengubah atau node tata letak yang digabungkannya.

Seperti ditunjukkan pada Gambar 2, penerapan composable Image dan Text itu sendiri terdiri dari rantai pengubah yang menggabungkan satu node tata letak.

Penerapan Row dan Column adalah node tata letak yang menjelaskan cara menata letak turunannya.

Struktur hierarki dari sebelumnya, tetapi sekarang setiap node hanyalah tata letak sederhana, dengan banyak node pembungkus pengubah di sekitarnya.
Gambar 2. Struktur hierarki yang sama seperti pada Gambar 1, tetapi dengan composable di hierarki UI yang divisualisasikan sebagai rantai pengubah.

Ringkasnya:

  • Pengubah menggabungkan satu pengubah atau node tata letak.
  • Node tata letak dapat menata letak beberapa node turunan.

Bagian berikut menjelaskan cara menggunakan model mental ini untuk memahami rantai pengubah dan pengaruhnya terhadap ukuran composable.

Batasan dalam fase tata letak

Fase tata letak mengikuti algoritma tiga langkah untuk menemukan lebar, tinggi, dan koordinat x, y setiap node tata letak:

  1. Mengukur turunan: Node mengukur turunannya, jika ada.
  2. Menentukan ukuran sendiri: Berdasarkan pengukuran tersebut, node menentukan ukurannya sendiri.
  3. Menempatkan turunan: Setiap node turunan ditempatkan relatif terhadap posisi node itu sendiri.

Constraints membantu menemukan ukuran yang tepat untuk node selama dua langkah pertama algoritma. Batasan menentukan batas minimum dan maksimum untuk lebar dan tinggi node. Saat node menentukan ukurannya, ukuran yang diukur harus berada dalam rentang ukuran ini.

Jenis batasan

Batasan dapat berupa salah satu hal berikut:

  • Terbatas: Node memiliki lebar dan tinggi maksimum dan minimum.
Batasan terikat dengan ukuran berbeda dalam penampung.
Gambar 3. Batasan terbatas.
  • Tidak terbatas: Node tidak dibatasi ke ukuran apa pun. Batas lebar dan tinggi maksimum ditetapkan ke tak terbatas.
Batasan tidak terikat yang memiliki lebar dan tinggi yang ditetapkan ke tak terhingga. Batasan melampaui penampung.
Gambar 4. Batasan tidak terbatas.
  • Tepat: Node diminta untuk mengikuti persyaratan ukuran yang tepat. Batas minimum dan maksimum ditetapkan ke nilai yang sama.
Batasan persis yang sesuai dengan persyaratan ukuran persis dalam penampung.
Gambar 5. Batasan tepat.
  • Kombinasi: Node mengikuti kombinasi jenis batasan sebelumnya. Misalnya, batasan dapat membatasi lebar sekaligus memungkinkan tinggi maksimum yang tidak terbatas, atau menetapkan lebar yang tepat tetapi memberikan tinggi yang terbatas.
Dua penampung yang menampilkan kombinasi batasan terikat dan tidak terikat serta lebar dan tinggi yang tepat.
Gambar 6. Kombinasi batasan terbatas dan tidak terbatas serta lebar dan tinggi yang tepat.

Bagian berikutnya menjelaskan cara batasan ini diteruskan dari induk ke turunan.

Cara batasan diteruskan dari induk ke turunan

Selama langkah pertama algoritma yang dijelaskan dalam Batasan dalam fase tata letak, batasan diteruskan dari induk ke turunan di hierarki UI.

Saat node induk mengukur turunannya, node induk akan memberikan batasan ini kepada setiap turunan untuk memberi tahu seberapa besar atau kecil ukuran yang diizinkan. Kemudian, saat menentukan ukurannya sendiri, node induk juga mematuhi batasan yang diteruskan oleh induknya sendiri.

Pada tingkat tinggi, algoritma berfungsi dengan cara berikut:

  1. Untuk menentukan ukuran yang sebenarnya ingin ditempati, node root di hierarki UI mengukur turunannya dan meneruskan batasan yang sama ke turunan pertamanya.
  2. Jika turunan adalah pengubah yang tidak memengaruhi pengukuran, turunan akan meneruskan batasan ke pengubah berikutnya. Batasan diteruskan ke rantai pengubah apa adanya kecuali jika pengubah yang memengaruhi pengukuran tercapai. Kemudian, batasan akan diubah ukurannya sesuai dengan itu.
  3. Setelah node yang tidak memiliki turunan tercapai (disebut sebagai "node leaf"), node tersebut akan menentukan ukurannya berdasarkan batasan yang diteruskan, dan menampilkan ukuran yang diatasi ini ke induknya.
  4. Induk menyesuaikan batasannya berdasarkan pengukuran turunan ini, dan memanggil turunan berikutnya dengan batasan yang disesuaikan ini.
  5. Setelah semua turunan induk diukur, node induk akan menentukan ukurannya sendiri dan mengomunikasikannya ke induknya sendiri.
  6. Dengan cara ini, seluruh hierarki akan dilalui secara depth-first. Pada akhirnya, semua node telah menentukan ukurannya, dan langkah pengukuran selesai.

Untuk contoh mendalam, lihat video Batasan dan urutan pengubah.

Pengubah yang memengaruhi batasan

Anda telah mempelajari di bagian sebelumnya bahwa beberapa pengubah dapat memengaruhi ukuran batasan. Bagian berikut menjelaskan pengubah tertentu yang memengaruhi batasan.

Pengubah size

Pengubah size mendeklarasikan ukuran konten yang diinginkan.

Misalnya, hierarki UI berikut harus dirender dalam penampung 300dp x 200dp. Batasannya terbatas, sehingga memungkinkan lebar antara 100dp dan 300dp, serta tinggi antara 100dp dan 200dp:

Sebagian hierarki UI dengan pengubah ukuran yang membungkus node tata letak, dan
  representasi set batasan yang dibatasi oleh pengubah ukuran dalam penampung.
Gambar 7. Batasan terbatas di hierarki UI dan representasinya dalam penampung.

Pengubah size menyesuaikan batasan masuk agar sesuai dengan nilai yang diteruskan ke pengubah tersebut. Dalam contoh ini, nilainya adalah 150dp:

Sama seperti Gambar 7, kecuali dengan pengubah ukuran yang menyesuaikan batasan masuk agar sesuai dengan nilai yang diteruskan kepadanya.
Gambar 8. Pengubah size yang menyesuaikan batasan ke 150dp.

Jika lebar dan tinggi lebih kecil dari batas batasan terkecil, atau lebih besar dari batas batasan terbesar, pengubah akan mencocokkan batasan yang diteruskan sedekat mungkin sambil tetap mematuhi batasan yang diteruskan:

Dua hierarki UI dan representasinya yang sesuai dalam penampung. Pada yang pertama, pengubah
  ukuran menerima batasan yang masuk; pada yang kedua, pengubah ukuran menyesuaikan dengan
  batasan yang terlalu besar sedekat mungkin, sehingga menghasilkan batasan yang mengisi penampung.
Gambar 9. Pengubah size yang mematuhi batasan yang diteruskan sedekat mungkin.

Perhatikan bahwa menggabungkan beberapa pengubah size tidak berfungsi. Pengubah size pertama menetapkan batasan minimum dan maksimum ke nilai tetap. Meskipun pengubah ukuran kedua meminta ukuran yang lebih kecil atau lebih besar, pengubah tersebut tetap harus mematuhi batas yang tepat yang diteruskan, sehingga tidak akan mengganti nilai tersebut:

Rantai dua pengubah ukuran di hierarki UI dan representasinya dalam penampung,
  yang merupakan hasil dari nilai pertama yang diteruskan dan bukan nilai kedua.
Gambar 10. Rantai dua pengubah size, yang nilai kedua yang diteruskan (50dp) tidak mengganti nilai pertama (100dp).

Pengubah requiredSize

Gunakan pengubah requiredSize dan bukan size jika Anda ingin node mengganti batasan masuk. Pengubah requiredSize mengganti batasan masuk dan meneruskan ukuran yang Anda tentukan sebagai batas yang tepat.

Saat ukuran diteruskan kembali ke hierarki, node turunan akan berada di tengah ruang yang tersedia:

Pengubah ukuran dan requiredSize yang dirangkai dalam hierarki UI, dan representasi
  yang sesuai dalam penampung. Batasan pengubah requiredSize menggantikan batasan pengubah ukuran.
Gambar 11. Pengubah requiredSize yang mengganti batasan masuk dari pengubah size.

Pengubah width dan height

Pengubah size menyesuaikan lebar dan tinggi batasan. Dengan pengubah width, Anda dapat menetapkan lebar tetap tetapi membiarkan tinggi tidak ditentukan. Demikian pula, dengan pengubah height, Anda dapat menetapkan tinggi tetap, tetapi membiarkan lebar tidak ditentukan:

Dua hierarki UI, satu dengan pengubah lebar dan representasi penampungnya, dan yang lainnya
  dengan pengubah tinggi dan representasinya.
Gambar 12. Pengubah width dan pengubah height yang menetapkan lebar dan tinggi tetap.

Pengubah sizeIn

Pengubah sizeIn memungkinkan Anda menetapkan batasan minimum dan maksimum yang tepat untuk lebar dan tinggi. Gunakan pengubah sizeIn jika Anda memerlukan kontrol terperinci atas batasan.

Pohon UI dengan pengubah sizeIn yang menetapkan lebar dan tinggi minimum dan maksimum,
  serta representasinya dalam penampung.
Gambar 13. Pengubah sizeIn dengan minWidth, maxWidth, minHeight, dan maxHeight ditetapkan.

Contoh

Bagian ini menunjukkan dan menjelaskan output dari beberapa cuplikan kode dengan pengubah berantai.

Image(
    painterResource(R.drawable.hero),
    contentDescription = null,
    Modifier
        .fillMaxSize()
        .size(50.dp)
)

Cuplikan ini menghasilkan output berikut:

Kotak biru yang mengisi penampung induknya.
Gambar 14. The Image mengisi ukuran maksimum sebagai hasil dari rantai pengubah.
  • Pengubah fillMaxSize mengubah batasan untuk menetapkan lebar dan tinggi minimum ke nilai maksimum — 300dp untuk lebar dan 200dp untuk tinggi.
  • Meskipun pengubah size ingin menggunakan ukuran 50dp, pengubah tersebut tetap harus mematuhi batasan minimum yang masuk. Jadi, pengubah size juga akan menampilkan batas batasan yang tepat sebesar 300 x 200, yang secara efektif mengabaikan nilai yang diberikan dalam pengubah size.
  • Image mengikuti batas ini dan melaporkan ukuran 300 x 200, yang diteruskan hingga ke hierarki.

Image(
    painterResource(R.drawable.hero),
    contentDescription = null,
    Modifier
        .fillMaxSize()
        .wrapContentSize()
        .size(50.dp)
)

Cuplikan ini menghasilkan output berikut:

Kotak biru kecil yang dipusatkan dalam penampung induknya.
Gambar 15. The Image berada di tengah dan berukuran 50dp.
  • Pengubah fillMaxSize menyesuaikan batasan untuk menetapkan lebar dan tinggi minimum ke nilai maksimum — 300dp untuk lebar dan 200dp untuk tinggi.
  • Pengubah wrapContentSize mereset batasan minimum. Jadi, meskipun fillMaxSize menghasilkan batasan tetap, wrapContentSize meresetnya kembali ke batasan terbatas. Node berikut kini dapat menempati seluruh ruang lagi, atau lebih kecil dari seluruh ruang.
  • Pengubah size menetapkan batasan ke batas minimum dan maksimum 50.
  • Image diatasi ke ukuran 50 x 50, dan pengubah size meneruskannya.
  • Pengubah wrapContentSize memiliki properti khusus. Pengubah ini mengambil turunannya dan menempatkannya di tengah batas minimum yang tersedia yang diteruskan ke pengubah tersebut. Oleh karena itu, ukuran yang dikomunikasikan ke induknya sama dengan batas minimum yang diteruskan ke pengubah tersebut.

Dengan menggabungkan tiga pengubah saja, Anda dapat menentukan ukuran untuk composable dan menempatkannya di tengah induknya.

Image(
    painterResource(R.drawable.hero),
    contentDescription = null,
    Modifier
        .clip(CircleShape)
        .padding(10.dp)
        .size(100.dp)
)

Cuplikan ini menghasilkan output berikut:

Bentuk lingkaran yang dipangkas dengan salah karena urutan pengubah.
Gambar 16. Bentuk yang dipangkas secara salah karena urutan pengubah order.
  • Pengubah clip tidak mengubah batasan.
  • Pengubah padding menurunkan batasan maksimum.
  • Pengubah size menetapkan semua batasan ke 100dp.
  • Image mematuhi batasan tersebut dan melaporkan ukuran 100dp x 100dp.
  • Pengubah padding menambahkan 10dp di semua sisi ke ukuran yang dilaporkan oleh Image, sehingga tata letak dengan padding melaporkan lebar dan tinggi 120dp.
  • Sekarang, pada fase gambar, pengubah clip bertindak pada kanvas 120dp x 120dp. Pengubah ini membuat mask lingkaran dengan ukuran tersebut.
  • Kemudian, pengubah padding menyisipkan kontennya sebesar 10dp di semua sisi, yang menurunkan ukuran kanvas untuk Image menjadi 100dp x 100dp.
  • Image digambar di kanvas yang lebih kecil tersebut. Gambar dipangkas berdasarkan lingkaran asli 120dp, sehingga outputnya adalah hasil yang tidak bulat.