ConstraintLayout, composable'ları ekrandaki diğer composable'lara göre yerleştirmenize olanak tanıyan bir düzendir. Bu özellik, iç içe yerleştirilmiş birden fazla Row, Column, Box ve diğer özel düzen öğelerini kullanmaya alternatif bir yöntemdir. ConstraintLayout
Daha karmaşık hizalama gereksinimlerine sahip daha büyük düzenler uygularken kullanışlıdır.
Aşağıdaki senaryolarda ConstraintLayout kullanmayı düşünebilirsiniz:
- Öğeleri ekranda konumlandırmak için birden fazla
ColumnveRowiç içe yerleştirmekten kaçınarak kodun okunabilirliğini artırın. - Composable'ları diğer composable'lara göre veya kılavuzlara, engellere ya da zincirlere göre konumlandırmak için kullanılır.
Görünüm sisteminde, düz görünüm hiyerarşisi iç içe yerleştirilmiş görünümlere kıyasla performans açısından daha iyi olduğundan büyük ve karmaşık düzenler oluşturmak için ConstraintLayout önerilen yöntemdi. Ancak bu durum, derin düzen hiyerarşilerini verimli bir şekilde işleyebilen Compose'da sorun teşkil etmez.
ConstraintLayout hizmetini kullanmaya başla
Oluşturma'da ConstraintLayout özelliğini kullanmak için build.gradle'nize (Compose kurulumuna ek olarak) şu bağımlılığı eklemeniz gerekir:
implementation "androidx.constraintlayout:constraintlayout-compose:$constraintlayout_compose_version"
Oluşturma modundaki ConstraintLayout, DSL kullanılarak aşağıdaki şekilde çalışır:
ConstraintLayoutiçindeki her birleştirilebilir içincreateRefs()veyacreateRefFor()kullanarak referans oluşturun.- Kısıtlamalar, referansı parametre olarak alan ve kısıtlamalarını gövde lambda'sında belirtmenize olanak tanıyan
constrainAs()değiştiricisi kullanılarak sağlanır. - Kısıtlamalar,
linkTo()veya diğer faydalı yöntemler kullanılarak belirtilir. parent,ConstraintLayoutcomposable'ın kendisiyle ilgili kısıtlamaları belirtmek için kullanılabilecek mevcut bir referanstır.
ConstraintLayout kullanan bir composable örneğini aşağıda bulabilirsiniz:
@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) } ) } }
Bu kod, Button öğesinin üst kısmını 16.dp kenar boşluğuyla üst öğeye, Text öğesini de Button öğesinin alt kısmına yine 16.dp kenar boşluğuyla kısıtlar.
Button ve Text composable'ları, ConstraintLayout içinde birbirine bağlıdır.
Ayrılmış API
ConstraintLayout örneğinde, kısıtlamalar satır içi olarak belirtilir ve uygulandıkları composable'da bir değiştirici bulunur. Ancak, kısıtlamaları uygulandıkları düzenlerden ayırmanın tercih edileceği durumlar da vardır. Örneğin, kısıtlamaları ekran yapılandırmasına göre değiştirmek veya iki kısıtlama grubu arasında animasyon oluşturmak isteyebilirsiniz.
Bu gibi durumlarda ConstraintLayout parametresini farklı bir şekilde kullanabilirsiniz:
ConstraintLayoutişlevine parametre olarakConstraintSetiletin.ConstraintSetiçinde oluşturulan referansları,layoutIddeğiştiricisini kullanarak composable'lara atayın.
@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) } } }
Ardından, kısıtlamaları değiştirmeniz gerektiğinde farklı bir ConstraintSet iletebilirsiniz.
ConstraintLayout kavramları
ConstraintLayout, composable'ınızdaki öğeleri konumlandırmanıza yardımcı olabilecek yönergeler, engeller ve zincirler gibi kavramlar içerir.
Kurallar
Kılavuzlar, düzen tasarlarken kullanılan küçük görsel yardımcılar. Composable'lar bir kılavuz çizgisiyle sınırlandırılabilir. Kılavuzlar, öğeleri üst composable'ın içinde belirli bir dp veya percentage konumuna yerleştirmek için kullanışlıdır.
Dikey ve yatay olmak üzere iki farklı türde yönergeler vardır. İki yatay olan top ve bottom, iki dikey olan ise start ve end'dür.
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) }
Bir yönerge oluşturmak için createGuidelineFrom* ile gerekli yönerge türünü kullanın. Bu, Modifier.constrainAs() bloğunda kullanılabilecek bir referans oluşturur.
Bariyerler
Barriers (Engeller), belirtilen taraftaki en uç widget'a dayalı sanal bir kılavuz çizgisi oluşturmak için birden fazla composable'a referans verir.
Engel oluşturmak için createTopBarrier() (veya: createBottomBarrier(), createEndBarrier(), createStartBarrier()) simgesini kullanın ve engeli oluşturacak referansları girin.
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val topBarrier = createTopBarrier(button, text) } }
Bu bariyer daha sonra Modifier.constrainAs() bloğunda kullanılabilir.
Zincirler
Zincirler, tek bir eksende (yatay veya dikey) grup benzeri davranışlar sağlar. Diğer eksen bağımsız olarak kısıtlanabilir.
Zincir oluşturmak için createVerticalChain veya createHorizontalChain simgesini kullanın:
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) } }
Daha sonra zincir, Modifier.constrainAs() bloğunda kullanılabilir.
Bir zincir, birleştirilebilir öğeyi çevreleyen alanla nasıl başa çıkılacağını belirleyen farklı ChainStyles ile yapılandırılabilir. Örneğin:
ChainStyle.Spread: Boşluk, ilk composable'dan önceki ve son composable'dan sonraki boş alan da dahil olmak üzere tüm composable'lara eşit şekilde dağıtılır.ChainStyle.SpreadInside: Boşluk, tüm composable'lar arasında eşit olarak dağıtılır. İlk composable'dan önce veya son composable'dan sonra boş alan olmaz.ChainStyle.Packed: Boşluk, ilk composable'dan önce ve son composable'dan sonra dağıtılır. Composables, aralarında boşluk olmadan birbirine yakın şekilde yerleştirilir.
Daha fazla bilgi
ConstraintLayout kullanan beste örneklerinde, Beste'de ConstraintLayout ile ilgili daha fazla bilgi edinin.