ConstraintLayout در Compose

ConstraintLayout طرحی است که به شما امکان می دهد تا composable ها را نسبت به دیگر composable ها روی صفحه قرار دهید. این یک جایگزین برای استفاده از چند Row تو در تو , Column , Box و دیگر عناصر طرح سفارشی است . ConstraintLayout هنگام اجرای طرح‌بندی‌های بزرگتر با الزامات ترازبندی پیچیده‌تر مفید است.

استفاده از ConstraintLayout را در سناریوهای زیر در نظر بگیرید:

  • برای جلوگیری از تودرتو شدن چندین Column و Row برای تعیین موقعیت عناصر روی صفحه به منظور بهبود خوانایی کد.
  • قرار دادن کامپوزیشن‌ها نسبت به سایر مواد ترکیب‌پذیر یا قرار دادن مواد ترکیب‌پذیر بر اساس دستورالعمل‌ها، موانع یا زنجیره‌ها.

در سیستم View، ConstraintLayout روش پیشنهادی برای ایجاد طرح‌بندی‌های بزرگ و پیچیده بود، زیرا سلسله مراتب نمای مسطح برای عملکرد بهتر از نماهای تودرتو بود. با این حال، این یک نگرانی در Compose نیست، زیرا می تواند به طور موثر سلسله مراتب طرح بندی عمیق را مدیریت کند.

با ConstraintLayout شروع کنید

برای استفاده از ConstraintLayout در Compose، باید این وابستگی را در build.gradle خود اضافه کنید (علاوه بر تنظیم Compose ):

implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"

ConstraintLayout در Compose به روش زیر با استفاده از یک DSL کار می کند:

  • با استفاده از createRefs() یا createRefFor() برای هر composable در ConstraintLayout مرجع ایجاد کنید.
  • محدودیت‌ها با استفاده از اصلاح‌کننده constrainAs() ارائه می‌شوند، که مرجع را به عنوان پارامتر می‌گیرد و به شما امکان می‌دهد محدودیت‌های آن را در بدنه لامبدا مشخص کنید.
  • محدودیت ها با استفاده از linkTo() یا سایر روش های مفید مشخص می شوند.
  • parent یک مرجع موجود است که می تواند برای تعیین محدودیت ها نسبت به خود ConstraintLayout composable استفاده شود.

در اینجا یک مثال از یک Composable با استفاده از 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 محدود می کند.

یک دکمه و یک عنصر متنی را که در یک ConstraintLayout مرتب شده اند نشان می دهد

API جدا شده

در مثال ConstraintLayout ، محدودیت‌ها به صورت خطی مشخص شده‌اند، با یک اصلاح‌کننده در composable که روی آن اعمال می‌شوند. با این حال، موقعیت‌هایی وجود دارد که ترجیح داده می‌شود محدودیت‌ها را از طرح‌بندی‌هایی که برای آنها اعمال می‌شود جدا کنیم. به عنوان مثال، ممکن است بخواهید محدودیت ها را بر اساس پیکربندی صفحه تغییر دهید یا بین دو مجموعه محدودیت متحرک کنید.

برای مواردی مانند این، می توانید از ConstraintLayout به روش دیگری استفاده کنید:

  1. یک ConstraintSet به عنوان پارامتر به ConstraintLayout منتقل کنید.
  2. ارجاعات ایجاد شده در ConstraintSet را با استفاده از اصلاح کننده layoutId به composable ها اختصاص دهید.

@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 حاوی مفاهیمی مانند دستورالعمل‌ها، موانع و زنجیره‌هایی است که می‌توانند به موقعیت‌یابی عناصر در داخل Composable شما کمک کنند.

رهنمودها

راهنماها کمک‌های بصری کوچکی برای طراحی طرح‌بندی هستند. ترکیب‌پذیرها را می‌توان به یک دستورالعمل محدود کرد. رهنمودها برای قرار دادن عناصر در یک 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 : فضا قبل از اولین و بعد از آخرین ترکیب توزیع می شود، اجزای سازنده بدون فاصله بین یکدیگر در کنار هم قرار می گیرند.

بیشتر بدانید

درباره ConstraintLayout در Compose از APIهای در حال کار در نمونه های Compose که از ConstraintLayout استفاده می کنند بیشتر بیاموزید.

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}