กฎข้อหนึ่งของ Compose คือคุณควรวัดองค์ประกอบย่อยเพียงครั้งเดียว การวัดองค์ประกอบย่อย 2 ครั้งจะทำให้เกิดข้อยกเว้นรันไทม์ อย่างไรก็ตาม มีบางครั้งที่คุณจำเป็นต้องทราบข้อมูลบางอย่างเกี่ยวกับบุตรหลานก่อนที่จะวัด
Intrinsics ช่วยให้คุณสอบถามเด็กๆ ก่อนที่จะวัดผลจริงได้
คุณขอ IntrinsicSize.Min
หรือ IntrinsicSize.Max
ของ Composable ได้โดยทำดังนี้
Modifier.width(IntrinsicSize.Min)
- ความกว้างขั้นต่ำที่คุณต้องใช้เพื่อ แสดงเนื้อหาอย่างถูกต้องคือเท่าใดModifier.width(IntrinsicSize.Max)
- คุณต้องการความกว้างสูงสุดเท่าใดเพื่อแสดงเนื้อหาอย่างถูกต้องModifier.height(IntrinsicSize.Min)
- คุณต้องใช้ความสูงขั้นต่ำเท่าใด จึงจะแสดงเนื้อหาได้อย่างถูกต้องModifier.height(IntrinsicSize.Max)
- คุณต้องการความสูงสูงสุดเท่าใด เพื่อแสดงเนื้อหาอย่างถูกต้อง
เช่น หากคุณขอ minIntrinsicHeight
ของ Text
ที่มีข้อจำกัดเป็นอนันต์
width
ในเลย์เอาต์ที่กำหนดเอง ระบบจะแสดง height
ของ Text
พร้อมข้อความที่วาดในบรรทัดเดียว
การใช้งาน Intrinsics
คุณสร้าง Composable ที่แสดงข้อความ 2 รายการบนหน้าจอโดยคั่นด้วย เส้นแบ่งได้ดังนี้
โดยใช้ Row
ที่มี Composable 2 รายการของ Text
ที่เติมพื้นที่ว่าง และ Divider
ตรงกลาง Divider
ควรมีความสูงเท่ากับText
ที่สูงที่สุด และควรมีขนาดเล็ก (width = 1.dp
)
@Composable fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) { Row(modifier = modifier) { Text( modifier = Modifier .weight(1f) .padding(start = 4.dp) .wrapContentWidth(Alignment.Start), text = text1 ) VerticalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } }
Divider
ขยายเต็มหน้าจอ ซึ่งไม่ใช่ลักษณะการทำงานที่ต้องการ
ซึ่งเป็นเพราะ Row
วัดความสูงของแต่ละองค์ประกอบแยกกัน และใช้ความสูงของ Text
เพื่อจำกัด Divider
ไม่ได้
หากต้องการให้ Divider
เติมพื้นที่ว่างด้วยความสูงที่กำหนดแทน
ให้ใช้ตัวแก้ไข height(IntrinsicSize.Min)
height(IntrinsicSize.Min)
จะปรับขนาดองค์ประกอบย่อยให้มีความสูงเท่ากับความสูงขั้นต่ำ
โดยธรรมชาติ เนื่องจากตัวแก้ไขนี้เป็นแบบเรียกซ้ำ จึงจะค้นหา minIntrinsicHeight
ของ Row
และองค์ประกอบย่อย
การใช้ตัวแก้ไขนี้กับโค้ดจะทำให้โค้ดทำงานได้ตามที่คาดไว้
@Composable fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) { Row(modifier = modifier.height(IntrinsicSize.Min)) { Text( modifier = Modifier .weight(1f) .padding(start = 4.dp) .wrapContentWidth(Alignment.Start), text = text1 ) VerticalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } } // @Preview @Composable fun TwoTextsPreview() { MaterialTheme { Surface { TwoTexts(text1 = "Hi", text2 = "there") } } }
เมื่อแสดงตัวอย่าง
ความสูงของ Row
จะกำหนดดังนี้
Row
ของminIntrinsicHeight
ที่ประกอบได้คือค่าสูงสุดminIntrinsicHeight
ขององค์ประกอบย่อยminIntrinsicHeight
ขององค์ประกอบDivider
คือ 0 เนื่องจากไม่ได้ใช้พื้นที่หากไม่มีข้อจำกัดText
minIntrinsicHeight
คือข้อความสำหรับwidth
ที่เฉพาะเจาะจง- ดังนั้นข้อจํากัด
height
ขององค์ประกอบRow
จึงกลายเป็นค่าสูงสุดminIntrinsicHeight
ของText
- จากนั้น
Divider
จะขยายheight
ไปยังข้อจํากัดheight
ที่กําหนดโดยRow
องค์ประกอบภายในในเลย์เอาต์ที่กำหนดเอง
เมื่อสร้างตัวแก้ไข Layout
หรือ layout
ที่กำหนดเอง ระบบจะคำนวณการวัดค่าโดยธรรมชาติ
โดยอัตโนมัติตามค่าประมาณ ดังนั้น
การคำนวณอาจไม่ถูกต้องสำหรับเลย์เอาต์บางแบบ API เหล่านี้มีตัวเลือก
ในการลบล้างค่าเริ่มต้นเหล่านี้
หากต้องการระบุการวัดค่าภายในของ Layout
ที่กำหนดเอง ให้ลบล้าง
minIntrinsicWidth
, minIntrinsicHeight
, maxIntrinsicWidth
และ
maxIntrinsicHeight
ของอินเทอร์เฟซ MeasurePolicy
เมื่อสร้าง
@Composable fun MyCustomComposable( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( content = content, modifier = modifier, measurePolicy = object : MeasurePolicy { override fun MeasureScope.measure( measurables: List<Measurable>, constraints: Constraints ): MeasureResult { // Measure and layout here // ... } override fun IntrinsicMeasureScope.minIntrinsicWidth( measurables: List<IntrinsicMeasurable>, height: Int ): Int { // Logic here // ... } // Other intrinsics related methods have a default value, // you can override only the methods that you need. } ) }
เมื่อสร้างlayout
ตัวปรับแต่งที่กำหนดเอง ให้ลบล้างเมธอดที่เกี่ยวข้อง
ในอินเทอร์เฟซ LayoutModifier
fun Modifier.myCustomModifier(/* ... */) = this then object : LayoutModifier { override fun MeasureScope.measure( measurable: Measurable, constraints: Constraints ): MeasureResult { // Measure and layout here // ... } override fun IntrinsicMeasureScope.minIntrinsicWidth( measurable: IntrinsicMeasurable, height: Int ): Int { // Logic here // ... } // Other intrinsics related methods have a default value, // you can override only the methods that you need. }
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- เลย์เอาต์ที่กำหนดเอง {:#custom-layouts}
- เส้นแนวใน Jetpack Compose
- ระยะต่างๆ ของ Jetpack Compose