ConstraintLayout, composable'ları ekrandaki diğer composable'lara göre yerleştirmenize olanak tanıyan bir düzendir. İç içe yerleştirilmiş birden fazla Row, Column, Box ve diğer özel düzen öğelerini kullanmaya alternatif bir yöntemdir.
Görünüm sisteminde, düz görünüm hiyerarşisi performans açısından iç içe yerleştirilmiş görünümlerden daha iyi olduğundan büyük ve karmaşık düzenler oluşturmak için ConstraintLayout öneriliyordu. Ancak bu durum, derin düzen hiyerarşilerini verimli bir şekilde işleyebilen Compose'da bir sorun teşkil etmez. Bu nedenle ConstraintLayout o kadar faydalı değildir.
ConstraintLayout çözümünü kullanmaya başlayın
Compose'da ConstraintLayout kullanmak için bu bağımlılığı build.gradle dosyanıza eklemeniz gerekir (Compose kurulumuna ek olarak):
implementation "androidx.constraintlayout:constraintlayout-compose:$constraintlayout_compose_version"
Compose'da ConstraintLayout, DSL kullanarak aşağıdaki şekilde çalışır:
createRefs()veyacreateRefFor()kullanarakConstraintLayoutiçindeki her composable için referans oluşturun.- Kısıtlamalar, referansı parametre olarak alan ve kısıtlamalarını gövde lambda'da 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ın kendisiyle ilgili kısıtlamaları belirtmek için kullanılabilecek mevcut bir referanstır.
ConstraintLayout kullanan bir composable örneği:
@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 ise Button öğesinin alt kısmına yine 16.dp kenar boşluğuyla kısıtlar.
ConstraintLayout içinde birbirine kısıtlanmış bir Button ve bir Text composable.
Bağımsız API
ConstraintLayout örneğinde kısıtlamalar, uygulandıkları composable'da bir değiştirici ile satır içinde belirtilir. Ancak kısıtlamaları, uygulandıkları düzenlerden ayırmanın tercih edildiğ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 özelliğini farklı bir şekilde kullanabilirsiniz:
ConstraintLayoutiçin parametre olarak birConstraintSetiletin.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 kavram
ConstraintLayout, composable'ınızdaki öğeleri konumlandırmanıza yardımcı olabilecek kılavuzlar, engeller ve zincirler gibi kavramlar içerir.
Kurallar
Kılavuz çizgileri, düzen tasarlarken kullanabileceğiniz küçük görsel yardımcılardır. Birleştirilebilir öğeler bir kılavuz çizgiyle sınırlandırılabilir. Kılavuz çizgileri, öğeleri üst composable'da belirli bir dp veya percentage konumuna yerleştirmek için kullanışlıdır.
Dikey ve yatay olmak üzere iki farklı kılavuz çizgi türü vardır. Yatay olanlar top ve bottom, dikey olanlar ise start ve 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) }
Kural oluşturmak için createGuidelineFrom* ile birlikte gerekli kural türünü kullanın. Bu işlem, Modifier.constrainAs() bloğunda kullanılabilecek bir referans oluşturur.
Engeller
Engeller, belirtilen taraftaki en uç widget'a göre sanal bir kılavuz oluşturmak için birden fazla composable'a referans verir.
Bariyer oluşturmak için createTopBarrier() (veya: createBottomBarrier(), createEndBarrier(), createStartBarrier()) kullanın ve bariyeri oluşturması gereken referansları sağlayın.
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val topBarrier = createTopBarrier(button, text) } }
Ardından bariyer, bir Modifier.constrainAs() bloğunda kullanılabilir.
Zincir
Zincirler, tek bir eksende (yatay veya dikey) grup benzeri davranış sağlar. Diğer eksen bağımsız olarak kısıtlanabilir.
Zincir oluşturmak için createVerticalChain veya createHorizontalChain 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) } }
Zincir daha sonra Modifier.constrainAs() bloğunda kullanılabilir.
Zincir, bir composable'ı çevreleyen alanın nasıl ele alınacağını belirleyen farklı ChainStyles ile yapılandırılabilir. Örneğin:
ChainStyle.Spread: Alan, ilk composable'dan önceki ve son composable'dan sonraki boş alan da dahil olmak üzere tüm composable'lara eşit olarak dağıtılır.ChainStyle.SpreadInside: Alan, tüm composable'lar arasında eşit olarak dağıtılır. İlk composable'dan önce veya son composable'dan sonra boş alan kalmaz.ChainStyle.Packed: Boşluk, ilk composable'dan önce ve son composable'dan sonra dağıtılır. Composable'lar, aralarında boşluk olmadan bir arada paketlenir.