ConstraintLayout ในการเขียน

ConstraintLayout เป็นเลย์เอาต์ที่ให้คุณวาง Composable เทียบกับ Composable อื่นๆ บนหน้าจอ เป็นอีกทางเลือกหนึ่งแทนที่จะใช้การซ้อนหลายระดับ Row, Column, Box และองค์ประกอบเลย์เอาต์ที่กำหนดเองอื่นๆ ConstraintLayout มีประโยชน์เมื่อใช้การจัดวางที่ใหญ่ขึ้น ซึ่งมีการจัดแนวที่ซับซ้อนมากขึ้น

พิจารณาใช้ ConstraintLayout ในสถานการณ์ต่อไปนี้

  • เพื่อหลีกเลี่ยงการซ้อน Column และ Row หลายรายการสําหรับตําแหน่งองค์ประกอบใน เพื่อให้โค้ดอ่านง่ายขึ้น
  • เพื่อจัดตำแหน่ง Composable เทียบกับ Composable อื่นหรือกับตำแหน่ง Composable ที่อิงตามหลักเกณฑ์ อุปสรรค หรือความเชื่อมโยง

ในระบบมุมมอง ConstraintLayout คือวิธีที่แนะนำในการสร้าง และเค้าโครงที่ซับซ้อนเพราะลำดับชั้นของมุมมองแนวราบจะมีประสิทธิภาพดีกว่า ก็คือมุมมองที่ซ้อนกัน อย่างไรก็ตาม การเขียนนี้ไม่สำคัญเท่าที่ควร จัดการลำดับชั้นของเลย์เอาต์แบบละเอียดได้อย่างมีประสิทธิภาพ

เริ่มต้นใช้งาน ConstraintLayout

หากต้องการใช้ ConstraintLayout ใน Compose คุณต้องเพิ่มทรัพยากร Dependency นี้ใน build.gradle (นอกเหนือจาก การตั้งค่าการเขียน)

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

ConstraintLayout ในการเขียนจะทำงานในลักษณะต่อไปนี้โดยใช้ DSL

  • สร้างการอ้างอิงสำหรับ Composable แต่ละรายการใน ConstraintLayout โดยใช้ createRefs() หรือ createRefFor()
  • มีการกำหนดข้อจำกัดโดยใช้ตัวแก้ไข constrainAs() ซึ่งจะใช้ เป็นพารามิเตอร์และให้คุณระบุข้อจำกัดในเนื้อความได้ แลมบ์ดา
  • ระบุข้อจำกัดโดยใช้ linkTo() หรือวิธีการอื่นๆ ที่เป็นประโยชน์
  • parent เป็นข้อมูลอ้างอิงที่มีอยู่ซึ่งใช้เพื่อระบุข้อจำกัดได้ ไปยัง Composable ของ ConstraintLayout

ต่อไปนี้คือตัวอย่างของ 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 ให้กับ Composable โดยใช้ ตัวปรับแต่ง 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 มีแนวคิดต่างๆ เช่น หลักเกณฑ์ อุปสรรค และห่วงโซ่ ซึ่งช่วยจัดตำแหน่งองค์ประกอบต่างๆ ใน Composable ได้

หลักเกณฑ์

หลักเกณฑ์เป็นตัวช่วยด้านภาพขนาดเล็กสำหรับออกแบบเลย์เอาต์ Composable อาจเป็น ให้เป็นไปตามหลักเกณฑ์ หลักเกณฑ์มีประโยชน์สำหรับการวางตำแหน่งองค์ประกอบ dp หรือ percentage บางอย่างภายใน Composable หลัก

หลักเกณฑ์มี 2 ประเภท ได้แก่ แนวตั้งและแนวนอน สอง แนวนอนคือ top และ bottom และประเภทธุรกิจ 2 รายการคือ 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()

สิ่งกีดขวาง

Barriers จะอ้างอิง Composable หลายรายการเพื่อสร้างหลักเกณฑ์เสมือนโดยอิงตาม วิดเจ็ตระดับสูงสุดในด้านที่ระบุ

หากต้องการสร้างกำแพง ให้ใช้ createTopBarrier() (หรือ createBottomBarrier() createEndBarrier(), createStartBarrier()) และระบุข้อมูลอ้างอิงที่ จะเป็นตัวกีดขวาง

ConstraintLayout {
    val constraintSet = ConstraintSet {
        val button = createRefFor("button")
        val text = createRefFor("text")

        val topBarrier = createTopBarrier(button, text)
    }
}

จากนั้นจะใช้อุปสรรคในบล็อก Modifier.constrainAs() ได้

เครือ

เชนมีลักษณะการทำงานที่คล้ายกลุ่มในแกนเดียว (แนวนอนหรือแนวตั้ง) ที่ใช้เวลาเพียง 2 นาที แกนอีกแกนหนึ่งสามารถจำกัดได้อย่างอิสระ

หากต้องการสร้างเชน ให้ใช้ 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ที่แตกต่างกัน ซึ่งจะเป็นตัวกำหนดวิธีการดีล ที่มีช่องว่างล้อมรอบ Composable เช่น:

  • ChainStyle.Spread: การเว้นวรรคจะกระจายเท่าๆ กันใน Composable ทั้งหมด รวมถึงพื้นที่ว่างก่อน Composable แรกและหลัง Composable
  • ChainStyle.SpreadInside: พื้นที่ทำงานจะกระจายอย่างเท่าๆ กันสำหรับองค์ประกอบทั้งหมด Composable โดยไม่มีพื้นที่ว่างก่อน Composable แรกหรือหลังจาก Composable ล่าสุด
  • ChainStyle.Packed: พื้นที่ทำงานจะกระจายอยู่ก่อนรายการแรกและหลัง Composable ล่าสุดจะต่อกันโดยไม่มีช่องว่างระหว่าง ระหว่างกัน

ดูข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมเกี่ยวกับ ConstraintLayout ใน Compose จากการทำงานของ API ใน เขียนตัวอย่างที่ใช้ ConstraintLayout