ConstraintLayout
คือเลย์เอาต์ที่ช่วยให้คุณวางคอมโพสิเบิลตามสัมพันธ์กับคอมโพสิเบิลอื่นๆ บนหน้าจอได้ ซึ่งเป็นอีกทางเลือกหนึ่งนอกเหนือจากการใช้ Row
, Column
, Box
และองค์ประกอบเลย์เอาต์ที่กำหนดเองอื่นๆ ที่ฝังไว้หลายรายการ ConstraintLayout
มีประโยชน์เมื่อใช้เลย์เอาต์ขนาดใหญ่ที่มีข้อกำหนดการจัดตำแหน่งที่ซับซ้อนมากขึ้น
พิจารณาใช้ ConstraintLayout
ในสถานการณ์ต่อไปนี้
- เพื่อหลีกเลี่ยงการฝัง
Column
และRow
หลายรายการเพื่อวางองค์ประกอบบนหน้าจอเพื่อปรับปรุงความอ่านง่ายของโค้ด - เพื่อวางองค์ประกอบที่คอมโพสิเบิลตามองค์ประกอบที่คอมโพสิเบิลอื่นๆ หรือวางองค์ประกอบที่คอมโพสิเบิลตามเส้นกํากับ สิ่งกีดขวาง หรือเชน
ในระบบมุมมอง ConstraintLayout
เป็นวิธีที่แนะนำในการสร้างเลย์เอาต์ขนาดใหญ่และซับซ้อน เนื่องจากลําดับชั้นมุมมองแบบแบนมีประสิทธิภาพดีกว่ามุมมองที่ฝัง แต่ข้อกังวลนี้ไม่มีใน Compose ซึ่งจัดการลําดับชั้นเลย์เอาต์แบบลําลึกได้อย่างมีประสิทธิภาพ
เริ่มต้นใช้งาน ConstraintLayout
หากต้องการใช้ ConstraintLayout
ใน Compose คุณต้องเพิ่มข้อกำหนดนี้ใน build.gradle
(นอกเหนือจากการตั้งค่า Compose)
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"
ConstraintLayout
ในเครื่องมือเขียนจะทํางานด้วยวิธีต่อไปนี้โดยใช้ DSL
- สร้างการอ้างอิงสำหรับคอมโพสิเบิลแต่ละรายการใน
ConstraintLayout
โดยใช้createRefs()
หรือcreateRefFor()
- ระบุข้อจำกัดโดยใช้ตัวแก้ไข
constrainAs()
ซึ่งจะใช้การอ้างอิงเป็นพารามิเตอร์และให้คุณระบุข้อจำกัดของข้อจำกัดนั้นในบอดี้ของ Lambda - ระบุข้อจำกัดโดยใช้
linkTo()
หรือวิธีการอื่นๆ ที่เป็นประโยชน์ parent
คือข้อมูลอ้างอิงที่มีอยู่ซึ่งสามารถใช้เพื่อระบุข้อจำกัดสำหรับ ComposableConstraintLayout
เอง
ตัวอย่างคอมโพสิเบิลที่ใช้ 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
ด้วย
API ที่แยกส่วน
ในตัวอย่าง ConstraintLayout
จะมีการระบุข้อจำกัดในบรรทัด โดยมีตัวแก้ไขในคอมโพสิเบิลที่ใช้ข้อจำกัด อย่างไรก็ตาม ก็มีบางกรณีที่ควรแยกข้อจำกัดออกจากเลย์เอาต์ที่ใช้ข้อจำกัดนั้น เช่น คุณอาจต้องการเปลี่ยนข้อจำกัดตามการกำหนดค่าหน้าจอ หรือสร้างภาพเคลื่อนไหวระหว่างชุดข้อจำกัด 2 ชุด
ในกรณีเช่นนี้ คุณสามารถใช้ 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
มีแนวคิดต่างๆ เช่น เส้นกํากับ สิ่งกีดขวาง และเชน ที่จะช่วยในการจัดตําแหน่งองค์ประกอบภายใน Composable
หลักเกณฑ์
หลักเกณฑ์คือตัวช่วยเล็กๆ ที่มองเห็นได้ซึ่งใช้ออกแบบเลย์เอาต์ คอมโพสิเบิลสามารถถูกจำกัดตามหลักเกณฑ์ได้ เส้นกํากับมีประโยชน์ในการวางองค์ประกอบที่ dp
หรือ percentage
ที่เจาะจงภายในคอมโพสิชันหลัก
หลักเกณฑ์มี 2 ประเภท ได้แก่ แนวตั้งและแนวนอน รูปภาพแนวนอน 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()
สิ่งกีดขวาง
สิ่งกีดขวางจะอ้างอิงคอมโพสิเบิลหลายรายการเพื่อสร้างเส้นกํากับเสมือนโดยอิงตามวิดเจ็ตด้านนอกสุดของด้านที่ระบุ
หากต้องการสร้างสิ่งกีดขวาง ให้ใช้ 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 ที่ใช้งานจริงในตัวอย่างการเขียนที่ใช้ ConstraintLayout
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- โฟกัสในโหมดเขียน
- Kotlin สำหรับ Jetpack Compose
- ข้อมูลเบื้องต้นเกี่ยวกับการจัดวาง