กฎข้อหนึ่งของ Compose คือคุณควรวัดบุตรหลานเพียงครั้งเดียว ที่วัดเด็กซ้ำ 2 ครั้ง จะทำให้เกิดข้อยกเว้นรันไทม์ อย่างไรก็ตาม บางครั้ง เมื่อต้องการข้อมูลเกี่ยวกับบุตรหลานก่อนที่จะวัดผล
Intrinsics ให้คุณค้นหาเด็กก่อนที่จะมีการวัดจริง
ใน Composable คุณจะขอ intrinsicWidth
หรือ intrinsicHeight
ได้:
(min|max)IntrinsicWidth
: จากความกว้างนี้ ค่าต่ำสุด/สูงสุดคือเท่าใด ที่กว้างที่สุดที่คุณสามารถกำหนด เนื้อหาอย่างเหมาะสมได้(min|max)IntrinsicHeight
: จากความสูงนี้ ค่าต่ำสุด/สูงสุดคือเท่าใด ความสูงที่คุณวาด เนื้อหาได้อย่างเหมาะสม
เช่น หากถาม minIntrinsicHeight
ของ Text
ที่มีอนันต์
height
ระบบจะแสดงผล height
ของ Text
ราวกับว่าข้อความถูกวาดใน
บรรทัดเดียว
การใช้งานภายใน
ลองจินตนาการว่าเราต้องการสร้าง Composable ที่แสดงข้อความ 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 ) Divider( 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 ) Divider( 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
ของ Composable ของ Row
จะเป็นค่าสูงสุด
minIntrinsicHeight
ของบุตรหลาน ขององค์ประกอบ Divider
minIntrinsicHeight
มีค่าเป็น 0 เนื่องจากไม่ได้ใช้พื้นที่หากไม่มีข้อจำกัด
ให้ Text
minIntrinsicHeight
จะเป็นข้อความที่ระบุ
width
ดังนั้น ข้อจำกัด height
ขององค์ประกอบ Row
จะเป็นค่าสูงสุด
minIntrinsicHeight
ของ Text
จากนั้น Divider
จะขยายheight
เป็น
ข้อจำกัด height
ที่กำหนดโดย Row
Intrinsics ในเลย์เอาต์ที่กำหนดเอง
เมื่อสร้างตัวแก้ไข 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