เลย์เอาต์ที่กำหนดเอง

ใน Compose องค์ประกอบ UI จะแสดงด้วยฟังก์ชันที่ใช้ได้กับ Compose ซึ่งจะปล่อย ชิ้นส่วน UI เมื่อเรียกใช้ จากนั้นจะเพิ่มลงในแผนผัง UI ที่แสดงผลบน หน้าจอ องค์ประกอบ UI แต่ละรายการมีองค์ประกอบหลัก 1 รายการและอาจมีองค์ประกอบย่อยหลายรายการ องค์ประกอบแต่ละรายการจะอยู่ในองค์ประกอบระดับบนด้วย โดยระบุเป็นตำแหน่ง (x, y) และขนาดที่ระบุเป็น width และ height

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

การวางโหนดแต่ละรายการในแผนผัง UI เป็นกระบวนการ 3 ขั้นตอน แต่ละโหนดต้องมีคุณสมบัติดังนี้

  1. วัดขนาดของเด็ก
  2. กำหนดขนาดของตัวเอง
  3. วางรายการย่อย

ขั้นตอนที่ 3 ของเลย์เอาต์โหนด: วัดขนาดของโหนดย่อย กำหนดขนาด และวางโหนดย่อย

การใช้ขอบเขตจะกำหนดเวลาที่คุณวัดและวางบุตรหลานได้ การวัดเลย์เอาต์จะทำได้ระหว่างการวัดและการส่งผ่านเลย์เอาต์เท่านั้น และวางองค์ประกอบย่อยได้ระหว่างการส่งผ่านเลย์เอาต์เท่านั้น (และหลังจากวัดแล้วเท่านั้น) เนื่องจากขอบเขตของ Compose เช่น MeasureScope และ PlacementScope จึงมีการบังคับใช้ในเวลาคอมไพล์

ใช้ตัวแก้ไขเลย์เอาต์

คุณใช้ตัวแก้ไข layout เพื่อแก้ไขวิธีวัดและจัดวางองค์ประกอบได้ Layout คือ Lambda โดยพารามิเตอร์ของ Lambda ประกอบด้วยองค์ประกอบที่คุณวัดได้ ซึ่งส่งเป็น measurable และข้อจำกัดขาเข้าของ Composable นั้น ซึ่งส่งเป็น constraints ตัวปรับแต่งเลย์เอาต์ที่กำหนดเองอาจมีลักษณะดังนี้

fun Modifier.customLayoutModifier() =
    layout { measurable, constraints ->
        // ...
    }

มาแสดง Text บนหน้าจอและควบคุมระยะห่างจากด้านบนถึง เส้นฐานของข้อความบรรทัดแรกกัน ซึ่งเป็นสิ่งที่ตัวแก้ไข paddingFromBaseline ทำอยู่พอดี เราจึงนำมาใช้ที่นี่เป็นตัวอย่าง โดยใช้ตัวแก้ไข layout เพื่อวาง Composable บนหน้าจอด้วยตนเอง นี่คือลักษณะการทำงานที่ต้องการเมื่อตั้งค่าTextระยะห่างด้านบน24.dp

แสดงความแตกต่างระหว่างระยะเว้นขอบ UI ปกติ ซึ่งกำหนดช่องว่างระหว่างองค์ประกอบ กับระยะเว้นขอบข้อความ ซึ่งกำหนดช่องว่างจากบรรทัดฐานหนึ่งไปยังอีกบรรทัดหนึ่ง

โค้ดที่ใช้สร้างระยะห่างดังกล่าวมีดังนี้

fun Modifier.firstBaselineToTop(
    firstBaselineToTop: Dp
) = layout { measurable, constraints ->
    // Measure the composable
    val placeable = measurable.measure(constraints)

    // Check the composable has a first baseline
    check(placeable[FirstBaseline] != AlignmentLine.Unspecified)
    val firstBaseline = placeable[FirstBaseline]

    // Height of the composable with padding - first baseline
    val placeableY = firstBaselineToTop.roundToPx() - firstBaseline
    val height = placeable.height + placeableY
    layout(placeable.width, height) {
        // Where the composable gets placed
        placeable.placeRelative(0, placeableY)
    }
}

โค้ดดังกล่าวมีลักษณะดังนี้

  1. ในmeasurableพารามิเตอร์แลมบ์ดา คุณจะวัดTextที่แสดงโดย พารามิเตอร์ที่วัดได้โดยการเรียกใช้ measurable.measure(constraints)
  2. คุณระบุขนาดของ Composable ได้โดยการเรียกใช้layout(width, height) เมธอด ซึ่งจะให้ Lambda ที่ใช้ในการวางองค์ประกอบที่ห่อไว้ด้วย ใน กรณีนี้คือความสูงระหว่างบรรทัดฐานสุดท้ายกับระยะห่างจากขอบด้านบนที่เพิ่ม
  3. คุณวางตำแหน่งองค์ประกอบที่ห่อไว้บนหน้าจอได้โดยเรียกใช้ placeable.place(x, y) หากไม่ได้วางองค์ประกอบที่ห่อไว้ องค์ประกอบเหล่านั้นจะไม่ แสดง yตำแหน่งจะสอดคล้องกับการเว้นวรรคด้านบน ซึ่งเป็นตำแหน่งของ บรรทัดฐานแรกของข้อความ

หากต้องการยืนยันว่าการทำงานเป็นไปตามที่คาดไว้ ให้ใช้ตัวแก้ไขนี้กับ Text

@Preview
@Composable
fun TextWithPaddingToBaselinePreview() {
    MyApplicationTheme {
        Text("Hi there!", Modifier.firstBaselineToTop(32.dp))
    }
}

@Preview
@Composable
fun TextWithNormalPaddingPreview() {
    MyApplicationTheme {
        Text("Hi there!", Modifier.padding(top = 32.dp))
    }
}

ตัวอย่างองค์ประกอบข้อความหลายรายการ โดยรายการหนึ่งแสดงระยะห่างปกติระหว่างองค์ประกอบ ส่วนอีกรายการแสดงระยะห่างจากบรรทัดฐานหนึ่งไปยังอีกบรรทัดฐานหนึ่ง

สร้างเลย์เอาต์ที่กำหนดเอง

layout ตัวแก้ไขจะเปลี่ยนเฉพาะ Composable ของการโทร หากต้องการวัดและจัดวาง Composable หลายรายการ ให้ใช้ Composable Layout แทน ซึ่งช่วยให้คุณวัดและวางเลย์เอาต์องค์ประกอบย่อยด้วยตนเองได้ เลย์เอาต์ระดับสูงทั้งหมด เช่น Column และ Row สร้างขึ้นด้วย Layout ที่ใช้ร่วมกันได้

มาสร้างเวอร์ชันพื้นฐานของ Column กัน เลย์เอาต์ที่กำหนดเองส่วนใหญ่มีรูปแบบดังนี้

@Composable
fun MyBasicColumn(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        // measure and position children given constraints logic here
        // ...
    }
}

measurables คือรายการขององค์ประกอบย่อยที่ต้องวัด และ constraints คือข้อจำกัดจากองค์ประกอบหลัก ซึ่งคล้ายกับตัวแก้ไข layout MyBasicColumn สามารถติดตั้งใช้งานได้ดังนี้ตามตรรกะเดียวกับก่อนหน้า

@Composable
fun MyBasicColumn(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        // Don't constrain child views further, measure them with given constraints
        // List of measured children
        val placeables = measurables.map { measurable ->
            // Measure each children
            measurable.measure(constraints)
        }

        // Set the size of the layout as big as it can
        layout(constraints.maxWidth, constraints.maxHeight) {
            // Track the y co-ord we have placed children up to
            var yPosition = 0

            // Place children in the parent layout
            placeables.forEach { placeable ->
                // Position item on the screen
                placeable.placeRelative(x = 0, y = yPosition)

                // Record the y co-ord placed up to
                yPosition += placeable.height
            }
        }
    }
}

Composables ขององค์ประกอบย่อยจะถูกจำกัดโดยข้อจำกัด Layout (ไม่มีข้อจำกัด minHeight) และจะวางตาม yPosition ของ Composables ก่อนหน้า

วิธีใช้ Composable ที่กำหนดเองมีดังนี้

@Composable
fun CallingComposable(modifier: Modifier = Modifier) {
    MyBasicColumn(modifier.padding(8.dp)) {
        Text("MyBasicColumn")
        Text("places items")
        Text("vertically.")
        Text("We've done it by hand!")
    }
}

องค์ประกอบข้อความหลายรายการซ้อนกันในคอลัมน์

ทิศทางเลย์เอาต์

เปลี่ยนทิศทางเลย์เอาต์ของ Composable โดยเปลี่ยน LocalLayoutDirection CompositionLocal

หากวาง Composable บนหน้าจอด้วยตนเอง LayoutDirection จะเป็นส่วนหนึ่งของ LayoutScope ของตัวแก้ไข layout หรือ Composable Layout

เมื่อใช้ layoutDirection ให้วาง Composable โดยใช้ place place จะไม่เปลี่ยนแปลงตามทิศทางของเลย์เอาต์ (จากซ้ายไปขวาเทียบกับจากขวาไปซ้าย) ซึ่งต่างจากวิธี placeRelative

การจัดวางที่กำหนดเองในการใช้งาน

ดูข้อมูลเพิ่มเติมเกี่ยวกับเลย์เอาต์และตัวแก้ไขได้ในเลย์เอาต์พื้นฐานใน Compose และดูเลย์เอาต์ที่กำหนดเองในการทำงานได้ในตัวอย่าง Compose ที่สร้างเลย์เอาต์ที่กำหนดเอง

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

หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับเลย์เอาต์ที่กำหนดเองใน Compose โปรดดูแหล่งข้อมูลเพิ่มเติมต่อไปนี้

วิดีโอ