ConstraintLayout هو تنسيق يتيح لك وضع الدوال المركّبة بالنسبة إلى
الدوال المركّبة الأخرى على الشاشة. وهي بديل لاستخدام عناصر متعددة متداخلة من Row وColumn وBox وعناصر التنسيق المخصّصة الأخرى.
في نظام View، كان ConstraintLayout هو الطريقة المقترَحة لإنشاء تصاميم كبيرة ومعقّدة، لأنّ هيكلية طرق العرض المسطّحة كانت أفضل للأداء من طرق العرض المتداخلة. ومع ذلك، لا يمثّل هذا مشكلة في Compose، الذي يمكنه التعامل بكفاءة مع التسلسلات الهرمية العميقة للتخطيط، لذا فإنّ ConstraintLayout ليس مفيدًا.
بدء المشاهدة مع "ConstraintLayout"
لاستخدام ConstraintLayout في Compose، عليك إضافة هذه التبعية في ملف
build.gradle (بالإضافة إلى إعداد Compose):
implementation "androidx.constraintlayout:constraintlayout-compose:$constraintlayout_compose_version"
تعمل ميزة ConstraintLayout في Compose بالطريقة التالية باستخدام
DSL:
- أنشئ مراجع لكل دالة مركّبة في
ConstraintLayoutباستخدامcreateRefs()أوcreateRefFor(). - يتم توفير القيود باستخدام المُعدِّل
constrainAs()، الذي يأخذ المرجع كمَعلمة ويتيح لك تحديد قيوده في دالة lambda الأساسية. - يتم تحديد القيود باستخدام
linkTo()أو طرق مفيدة أخرى. -
parentهو مرجع حالي يمكن استخدامه لتحديد القيود على الدالة المركّبةConstraintLayoutنفسها.
في ما يلي مثال على دالة مركّبة تستخدم 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) } ) } }
يقيّد هذا الرمز الجزء العلوي من Button إلى العنصر الرئيسي بهامش
16.dp وText إلى الجزء السفلي من Button أيضًا بهامش
16.dp.
Button ودالة مركّبة Text مقيّدتان ببعضهما في
ConstraintLayout.
واجهة برمجة تطبيقات منفصلة
في مثال ConstraintLayout، يتم تحديد القيود بشكل مضمّن، باستخدام
معدِّل في الدالة المركّبة التي يتم تطبيقها عليها. ومع ذلك، هناك حالات
يُفضَّل فيها فصل القيود عن التنسيقات التي تنطبق عليها.
على سبيل المثال، قد تحتاج إلى تغيير القيود بناءً على إعدادات الشاشة أو إضافة تأثيرات حركية بين مجموعتَي قيود.
في هذه الحالات، يمكنك استخدام ConstraintLayout بطريقة مختلفة:
- مرِّر
ConstraintSetكمَعلمة إلىConstraintLayout. - يمكنك تخصيص المراجع التي تم إنشاؤها في
ConstraintSetللدوال المركّبة باستخدام المُعدِّلlayoutId.
@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) } } }
بعد ذلك، عندما تحتاج إلى تغيير القيود، يمكنك فقط تمرير ConstraintSet مختلف.
ConstraintLayout مفهوم
يحتوي ConstraintLayout على مفاهيم مثل الإرشادات والحواجز والسلاسل
التي يمكن أن تساعد في تحديد موضع العناصر داخل الدالة المركّبة.
الإرشادات
الخطوط الإرشادية هي أدوات مساعدة مرئية صغيرة لتصميم التخطيطات بها. يمكن تقييد الدوال المركّبة
بإرشادات معيّنة. تُعدّ الإرشادات مفيدة لتحديد موضع العناصر في dp أو percentage معيّن داخل الدالة المركّبة الرئيسية.
هناك نوعان مختلفان من الإرشادات، الرأسية والأفقية. الخطان الأفقيان هما top وbottom، والخطان العموديان هما start و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) }
لإنشاء إرشادات، استخدِم createGuidelineFrom* مع نوع الإرشادات
المطلوبة. يؤدي ذلك إلى إنشاء مرجع يمكن استخدامه في كتلة Modifier.constrainAs().
الحواجز
تشير الحواجز إلى دوال مركّبة متعددة لإنشاء إرشادات افتراضية استنادًا إلى التطبيق المصغّر الأقصى على الجانب المحدّد.
لإنشاء حاجز، استخدِم createTopBarrier() (أو: createBottomBarrier() أو
createEndBarrier() أو createStartBarrier())، وقدِّم المراجع التي
يجب أن تشكّل الحاجز.
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val topBarrier = createTopBarrier(button, text) } }
ويمكن بعد ذلك استخدام الحاجز في مجموعة Modifier.constrainAs().
السلاسل
توفّر السلاسل سلوكًا يشبه سلوك المجموعة في محور واحد (أفقيًا أو عموديًا). يمكن تقييد المحور الآخر بشكل مستقل.
لإنشاء سلسلة، استخدِم إما createVerticalChain أو
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) } }
ويمكن بعد ذلك استخدام السلسلة في مجموعة Modifier.constrainAs().
يمكن ضبط سلسلة باستخدام ChainStyles مختلفة تحدّد كيفية التعامل مع المساحة المحيطة بدالة مركّبة، مثل:
-
ChainStyle.Spread: يتم توزيع المساحة بالتساوي على جميع الدوال المركّبة، بما في ذلك المساحة الفارغة قبل الدالة المركّبة الأولى وبعد الدالة المركّبة الأخيرة. -
ChainStyle.SpreadInside: يتم توزيع المساحة بالتساوي على جميع الدوال المركّبة، بدون أي مساحة فارغة قبل الدالة المركّبة الأولى أو بعد الدالة المركّبة الأخيرة. -
ChainStyle.Packed: يتم توزيع المسافة قبل الدالة المركّبة الأولى وبعد الدالة المركّبة الأخيرة، ويتم تجميع الدوال المركّبة معًا بدون مسافة بين بعضها البعض.