ConstraintLayout
adalah tata letak yang memungkinkan Anda menempatkan composable relatif terhadap
composable lain di layar. Ini adalah alternatif dari penggunaan beberapa elemen
Row
, Column
, dan Box
bertingkat, serta elemen tata letak kustom bertingkat lainnya. ConstraintLayout
berguna saat menerapkan tata letak yang lebih besar dengan
persyaratan perataan yang lebih rumit.
Sebaiknya gunakan ConstraintLayout
dalam skenario berikut:
- Untuk menghindari penyusunan bertingkat beberapa
Column
danRow
untuk penempatan elemen di layar guna meningkatkan keterbacaan kode. - Untuk menempatkan composable relatif terhadap composable lain atau untuk menempatkan composable berdasarkan panduan, batasan, atau rantai.
Dalam sistem View, ConstraintLayout
adalah cara yang disarankan untuk membuat
tata letak yang besar dan kompleks, karena hierarki tampilan yang datar lebih baik untuk performa
daripada tampilan bertingkat. Namun, hal ini bukan suatu masalah di Compose, yang dapat
menangani hierarki tata letak dalam secara efisien.
Persiapan untuk ConstraintLayout
Untuk menggunakan ConstraintLayout
di Compose, Anda perlu menambahkan dependensi ini di
build.gradle
(selain
penyiapan Compose):
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"
ConstraintLayout
di Compose berfungsi dengan cara berikut menggunakan
DSL:
- Membuat referensi untuk setiap composable di
ConstraintLayout
menggunakancreateRefs()
ataucreateRefFor()
- Batasan diberikan menggunakan pengubah
constrainAs()
, yang menggunakan referensi sebagai parameter dan memungkinkan Anda menentukan batasannya di lambda body. - Batasan ditentukan menggunakan
linkTo()
atau metode berguna lainnya. parent
adalah referensi yang sudah ada dan dapat digunakan untuk menentukan batasan terhadap composableConstraintLayout
itu sendiri.
Berikut ini contoh composable yang menggunakan ConstraintLayout
:
@Composable fun ConstraintLayoutContent() { ConstraintLayout { // Create references for the composables to constrain val (button, text) = createRefs() Button( onClick = { /* Do something */ }, // Assign reference "button" to the Button composable // and constrain it to the top of the ConstraintLayout modifier = Modifier.constrainAs(button) { top.linkTo(parent.top, margin = 16.dp) } ) { Text("Button") } // Assign reference "text" to the Text composable // and constrain it to the bottom of the Button composable Text( "Text", Modifier.constrainAs(text) { top.linkTo(button.bottom, margin = 16.dp) } ) } }
Kode ini membatasi bagian atas Button
untuk induk dengan margin
16.dp
dan Text
di bagian bawah Button
, juga dengan margin
16.dp
.
API terpisah
Pada contoh ConstraintLayout
,
batasan ditentukan sebagai bagian dari tata letak, dengan pengubah dalam composable
yang diterapkan. Namun, pada beberapa situasi, lebih baik memisahkan
batasan itu dari tata letak yang diterapkan. Misalnya, Anda mungkin ingin
mengubah batasan berdasarkan konfigurasi layar, atau membuat animasi di antara dua
kumpulan batasan.
Untuk kasus seperti ini, Anda dapat menggunakan ConstraintLayout
dengan cara lain:
- Teruskan
ConstraintSet
sebagai parameter keConstraintLayout
. - Tetapkan referensi yang dibuat di
ConstraintSet
ke composable menggunakan pengubahlayoutId
.
@Composable fun DecoupledConstraintLayout() { BoxWithConstraints { val constraints = if (minWidth < 600.dp) { decoupledConstraints(margin = 16.dp) // Portrait constraints } else { decoupledConstraints(margin = 32.dp) // Landscape constraints } ConstraintLayout(constraints) { Button( onClick = { /* Do something */ }, modifier = Modifier.layoutId("button") ) { Text("Button") } Text("Text", Modifier.layoutId("text")) } } } private fun decoupledConstraints(margin: Dp): ConstraintSet { return ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") constrain(button) { top.linkTo(parent.top, margin = margin) } constrain(text) { top.linkTo(button.bottom, margin) } } }
Kemudian, saat Anda perlu mengubah batasan, Anda dapat meneruskan ConstraintSet
yang berbeda.
Konsep ConstraintLayout
ConstraintLayout
berisi konsep seperti panduan, batasan, dan rantai
yang dapat membantu menempatkan elemen di dalam Composable.
Panduan
Panduan adalah bantuan visual kecil untuk mendesain tata letak. Composable dapat
dibatasi oleh panduan. Panduan berguna untuk menempatkan elemen di
dp
atau percentage
tertentu di dalam composable induk.
Ada dua jenis panduan yang berbeda, yaitu vertikal dan horizontal. Dua
panduan horizontal adalah top
dan bottom
, dan dua panduan vertikal adalah start
dan
end
.
ConstraintLayout { // Create guideline from the start of the parent at 10% the width of the Composable val startGuideline = createGuidelineFromStart(0.1f) // Create guideline from the end of the parent at 10% the width of the Composable val endGuideline = createGuidelineFromEnd(0.1f) // Create guideline from 16 dp from the top of the parent val topGuideline = createGuidelineFromTop(16.dp) // Create guideline from 16 dp from the bottom of the parent val bottomGuideline = createGuidelineFromBottom(16.dp) }
Untuk membuat panduan, gunakan createGuidelineFrom*
dengan jenis panduan
yang diperlukan. Tindakan ini akan membuat referensi yang dapat digunakan dalam
blok Modifier.constrainAs()
.
Batasan
Batasan mereferensikan beberapa composable untuk membuat panduan virtual berdasarkan widget yang paling ekstrem di sisi yang ditentukan.
Untuk membuat batasan, gunakan createTopBarrier()
(atau: createBottomBarrier()
,
createEndBarrier()
, createStartBarrier()
), dan berikan referensi yang
akan membuat batasan.
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val topBarrier = createTopBarrier(button, text) } }
Batasan ini kemudian dapat digunakan dalam blok Modifier.constrainAs()
.
Rantai
Rantai menyediakan perilaku seperti grup dalam satu sumbu (secara horizontal atau vertikal). Sumbu lain dapat dibatasi secara tersendiri.
Untuk membuat rantai, gunakan createVerticalChain
atau createHorizontalChain
:
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val verticalChain = createVerticalChain(button, text, chainStyle = ChainStyle.Spread) val horizontalChain = createHorizontalChain(button, text) } }
Rantai tersebut kemudian dapat digunakan dalam blok Modifier.constrainAs()
.
Rantai dapat dikonfigurasi dengan ChainStyles
berbeda, yang menentukan cara menangani
ruang di sekitar composable, seperti:
ChainStyle.Spread
: Ruang didistribusikan secara merata di seluruh composable, termasuk ruang kosong sebelum composable pertama dan setelah composable terakhir.ChainStyle.SpreadInside
: Ruang didistribusikan secara merata di seluruh composable, tanpa ruang kosong sebelum composable pertama atau setelah composable terakhir.ChainStyle.Packed
: Ruang didistribusikan sebelum composable pertama dan setelah composable terakhir, composable dikemas bersama tanpa spasi di antara satu sama lain.
Pelajari lebih lanjut
Pelajari lebih lanjut ConstraintLayout
di Compose dari cara kerja API dalam
contoh Compose yang menggunakan ConstraintLayout
.
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Fokus di Compose
- Kotlin untuk Jetpack Compose
- Dasar-dasar tata letak Compose