กฎข้อหนึ่งของ Compose คือคุณควรวัดค่าของบุตรหลานเพียงครั้งเดียวเท่านั้น การวัดค่าบุตรหลาน 2 ครั้งจะทำให้เกิดข้อยกเว้นรันไทม์ อย่างไรก็ตาม บางครั้งคุณก็จำเป็นต้องทราบข้อมูลบางอย่างเกี่ยวกับบุตรหลานก่อนทำการวัด
ข้อมูลพื้นฐานช่วยให้คุณค้นหาข้อมูลเกี่ยวกับเด็กได้ก่อนที่จะมีการวัดผลจริง
คุณสามารถขอ IntrinsicSize.Min
หรือ IntrinsicSize.Max
ของคอมโพสิเบิลได้โดยทำดังนี้
Modifier.width(IntrinsicSize.Min)
- คุณต้องแสดงเนื้อหาในขนาดความกว้างขั้นต่ำเท่าใดจึงจะเหมาะสมModifier.width(IntrinsicSize.Max)
- คุณต้องกำหนดความกว้างสูงสุดเท่าใดจึงจะแสดงเนื้อหาได้อย่างถูกต้องModifier.height(IntrinsicSize.Min)
- คุณต้องกำหนดความสูงขั้นต่ำเท่าใดเพื่อแสดงเนื้อหาอย่างเหมาะสมModifier.height(IntrinsicSize.Max)
- คุณต้องการความสูงสูงสุดเท่าใดเพื่อแสดงเนื้อหาอย่างเหมาะสม
เช่น หากคุณถาม minIntrinsicHeight
ของ Text
ที่มีข้อจำกัด width
แบบไม่จำกัดในเลย์เอาต์ที่กำหนดเอง ระบบจะแสดงผล height
ของ Text
ที่มีข้อความที่วาดเป็นบรรทัดเดียว
การใช้งาน Intrinsics
สมมติว่าเราต้องการสร้างคอมโพสิเบิลที่แสดงข้อความ 2 รายการบนหน้าจอโดยคั่นด้วยตัวแบ่ง เช่นนี้
เราจะดำเนินการนี้ได้อย่างไร เราอาจมี Row
ที่มี Text
2 ตัวอยู่ข้างในซึ่งขยายได้มากที่สุด และมี 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)
บังคับให้องค์ประกอบย่อยสูงเท่ากับความสูงขั้นต่ำตามธรรมชาติ เนื่องจากเป็นแบบซ้ำซ้อน ระบบจะค้นหา Row
และ minIntrinsicHeight
ซึ่งเป็นรายการย่อย
เมื่อนําไปใช้กับโค้ดของเรา โค้ดจะทํางานตามที่คาดไว้
@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") } } }
เมื่อใช้ฟีเจอร์แสดงตัวอย่าง
minIntrinsicHeight
ของคอมโพสิเบิล Row
จะเป็น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. }
แนะนำสำหรับคุณ
เลย์เอาต์ที่กำหนดเอง
Jetpack Compose is Android's recommended modern toolkit for building native UI. It simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.
การจัดแนวบรรทัดใน Jetpack Compose
Jetpack Compose is Android's recommended modern toolkit for building native UI. It simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.
เฟสของ Jetpack Compose
Jetpack Compose is Android's recommended modern toolkit for building native UI. It simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.