ตั้งค่าพร็อพเพอร์ตี้ของคอนเทนเนอร์

คุณสามารถกำหนดการกำหนดค่าคอนเทนเนอร์ Grid เพื่อสร้างเลย์เอาต์ที่ยืดหยุ่นซึ่งตอบสนองต่อขนาดหน้าจอและประเภทเนื้อหาที่แตกต่างกันได้ หน้านี้จะอธิบายวิธีการทำสิ่งต่อไปนี้

กำหนดตารางกริด

ตารางกริดประกอบด้วยคอลัมน์และแถว คอมโพสิเบิล Grid มีพารามิเตอร์ config ที่ยอมรับ Lambda เพื่อกำหนดคอลัมน์และแถวภายใน GridConfigurationScope ตัวอย่างต่อไปนี้กำหนดตารางกริดที่มี 3 แถวและ 2 คอลัมน์ โดยแต่ละแถวและคอลัมน์มีขนาดคงที่ซึ่งระบุไว้ใน Dp

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
    }
) {
}

วางรายการในตารางกริด

Grid จะนำองค์ประกอบ UI ใน Lambda content และวางลงในเซลล์ตารางกริด ตารางกริดจะจัดวางรายการต่างๆ ไม่ว่าคุณจะกำหนดแถวและคอลัมน์ไว้อย่างชัดเจนหรือไม่ก็ตาม โดยค่าเริ่มต้น Grid จะพยายามวางองค์ประกอบ UI ในเซลล์ตารางกริดที่ว่างในแถว หากทำไม่ได้ ระบบจะวางองค์ประกอบในเซลล์ตารางกริดที่ว่างในแถวถัดไป หากไม่มีเซลล์ว่าง Grid จะสร้างแถวใหม่

ในตัวอย่างต่อไปนี้ ตารางกริดมีเซลล์ตารางกริด 6 เซลล์และวางการ์ดไว้ในแต่ละเซลล์ (รูปที่ 1) เซลล์ตารางกริดแต่ละเซลล์มีขนาด 160dp x 90dp ทำให้ขนาดตารางกริดทั้งหมดเป็น 320dp x 270dp

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
    }
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

การ์ด 6 ใบวางอยู่ในตารางกริดที่มี 3 แถวและ 2 คอลัมน์
รูปที่ 1 การ์ด 6 ใบวางอยู่ในตารางกริดที่มี 3 แถวและ 2 คอลัมน์

หากต้องการเปลี่ยนลักษณะการทำงานเริ่มต้นนี้เป็นการเติมตามคอลัมน์ ให้ตั้งค่าพร็อพเพอร์ตี้ flow เป็น GridFlow.Column

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
        gap(8.dp)
        flow = GridFlow.Column // Grid tries to place items to fill the column
    },
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

ฟังก์ชันการจัดเรียงจะเปลี่ยนทิศทางในการวางรายการ
รูปที่ 2 GridFlow.Row (ซ้าย) และ GridFlow.Column (ขวา)

จัดการการปรับขนาดแทร็ก

แถวและคอลัมน์เรียกรวมกันว่าแทร็กตารางกริด คุณระบุขนาดของแทร็กตารางกริดได้โดยใช้วิธีใดวิธีหนึ่งต่อไปนี้

  • คงที่ (Dp): จัดสรรขนาดที่เจาะจง (เช่น column(180.dp))
  • เปอร์เซ็นต์ (Float): จัดสรรเปอร์เซ็นต์ของพื้นที่ว่างทั้งหมดจาก 0.0f เป็น 1.0f (เช่น row(0.5f) สำหรับ 50%)
  • ยืดหยุ่น (Fr): กระจายพื้นที่ที่เหลือตามสัดส่วนหลังจากคำนวณแทร็กแบบคงที่และแบบเปอร์เซ็นต์แล้ว เช่น หากตั้งค่า 2 แถวเป็น 1.fr และ 3.fr แถวหลังจะได้รับความสูงที่เหลือ 75%
  • Intrinsic: ปรับขนาดแทร็กตามเนื้อหาภายใน ดูข้อมูลเพิ่มเติมได้ที่กำหนดขนาดแทร็กตารางกริดโดยใช้ค่าภายใน

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

Grid(
    config = {
        column(1f)

        row(100.dp)
        row(0.2f)
        row(1.fr)
        row(GridTrackSize.Auto)
    },
    modifier = Modifier.height(480.dp)
) {
    PastelRedCard("Fixed(100.dp)")
        PastelGreenCard("Percentage(0.2f)")
    PastelBlueCard("Flex(1.fr)")
        PastelYellowCard("Auto")

}

ความสูงของแถวที่กำหนดโดยใช้ตัวเลือกการปรับขนาดแทร็กหลัก 4 รายการ
รูปที่ 3 ความสูงของแถวที่กำหนดโดยใช้ตัวเลือกการปรับขนาดแทร็กหลัก 4 รายการใน Grid

กำหนดขนาดขั้นต่ำสำหรับแทร็กตารางกริดแบบยืดหยุ่น

เมื่อคอนเทนเนอร์กริดไม่มีพื้นที่เหลือ แทร็กแบบยืดหยุ่นมาตรฐานจะหดเหลือ 0.dp ได้ เพื่อป้องกันปัญหานี้และตรวจสอบว่าเนื้อหาไม่ถูกบีบอัด ให้ใช้ GridTrackSize.MinMax เพื่อบังคับใช้ขนาดขั้นต่ำที่ชัดเจนในขณะที่ยังคงความยืดหยุ่นของแทร็กไว้

ตัวอย่างต่อไปนี้จะจัดสรรอย่างน้อย 100.dp ให้กับแถวแรก

Grid(
    config = {
        column(1f)
        // The first row has a minimum height of 100.dp and can expand to 
        // the half of the remaining space.
        row(GridTrackSize.MinMax(100.dp, 1.fr))
        // The second row takes the half of the remaining space.
        row(1.fr)
        // The third row has a fixed height of 200.dp.
        row(200.dp)
    },
    modifier = Modifier.size(360.dp) // Total grid height is 360.dp
) {
    PastelRedCard("MinMax(100.dp, 1.fr)")
        PastelGreenCard("Flex(1.fr)")
    PastelBlueCard("Fixed(200.dp)")
}

ความสูงของแถวที่กำหนดโดยใช้ตัวเลือกการปรับขนาดแทร็กหลัก 4 รายการ
รูปที่ 4 แถวแรกมีความสูงอย่างน้อย 100.dp

กำหนดขนาดแทร็กตารางกริดขั้นต่ำเพื่อวางรายการแบบ Lazy

แทร็กแบบยืดหยุ่นมาตรฐานจะค้นหาขนาดที่แท้จริงขององค์ประกอบย่อยโดยอัตโนมัติเพื่อกำหนดขนาดพื้นฐาน อย่างไรก็ตาม Jetpack Compose ไม่อนุญาตให้ค้นหาขนาดที่แท้จริงของ SubcomposeLayout ซึ่งรองรับคอมโพเนนต์ต่างๆ เช่น LazyColumn และ LazyRow

การวาง Lazy List ไว้ในแทร็กแบบยืดหยุ่นมาตรฐานจะทำให้เกิดข้อขัดข้อง IllegalStateException หากต้องการวาง Lazy List ไว้ในแทร็กตารางกริดที่ยืดหยุ่นได้อย่างปลอดภัย ให้ใช้ MinMax ที่มีขนาดขั้นต่ำที่ชัดเจน (เช่น 0.dp) เพื่อข้ามขั้นตอนการวัดค่าภายใน

Grid(
    config = {
        column(1f)
        // The first row's height is determined by the height of the Text composable.
        row(GridTrackSize.Auto)
        // The second row occupies the remaining space, allowing the LazyColumn to scroll.
        row(GridTrackSize.MinMax(0.dp, 1.fr))

        gap(8.dp)
    },
    modifier = Modifier.size(width = 170.dp, height = 240.dp)
) {
    Text("LazyColumn in a Grid")
    // The LazyColumn is placed in the second row, filling the remaining space.
    LazyColumn(verticalArrangement = Arrangement.spacedBy(4.dp)) {
        items(100) { number ->
            PastelGreenCard("Card $number")
        }
    }
}

ความสูงของแถวที่กำหนดโดยใช้ตัวเลือกการปรับขนาดแทร็กหลัก 4 รายการ
รูปที่ 5 LazyColumn ในเซลล์ตารางกริด

กำหนดขนาดแทร็กตารางกริดโดยเนื้อแท้

คุณสามารถใช้การปรับขนาดตามเนื้อหาสำหรับ Grid เมื่อต้องการให้เลย์เอาต์ปรับตามเนื้อหา แทนที่จะบังคับให้อยู่ในคอนเทนเนอร์แบบคงที่ ขนาดแทร็กตารางกริดจะกำหนดด้วยค่าต่อไปนี้

  • GridTrackSize.MaxContent: ใช้ขนาดที่แท้จริงสูงสุดของเนื้อหา (เช่น ความกว้างจะกำหนดโดยความยาวทั้งหมดของข้อความในบล็อกข้อความที่ไม่มีการตัดบรรทัด)
  • GridTrackSize.MinContent: ใช้ขนาดที่แท้จริงขั้นต่ำของเนื้อหา (เช่น ความกว้างจะกำหนดโดยคำเดี่ยวที่ยาวที่สุดในบล็อกข้อความ)
  • GridTrackSize.Auto: ใช้ขนาดที่ยืดหยุ่นสำหรับแทร็กที่ปรับตามพื้นที่ว่างที่มีอยู่ โดยค่าเริ่มต้นจะทำงานเหมือน MaxContent แต่จะย่อและรวมเนื้อหาให้พอดีกับคอนเทนเนอร์หลัก

ตัวอย่างต่อไปนี้วางข้อความ 2 รายการไว้ข้างกัน ขนาดคอลัมน์สำหรับข้อความแรกจะกำหนดโดยความกว้างขั้นต่ำที่จำเป็นในการแสดงข้อความ และความกว้างของคอลัมน์ที่ 2 จะขึ้นอยู่กับความกว้างสูงสุดที่จำเป็นของข้อความ

Grid(
    config = {
        column(GridTrackSize.MinContent)
        column(GridTrackSize.MaxContent)
        row(1.0f)
    },
    modifier = Modifier.width(480.dp)
) {
    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet.")
    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet.")
}

ขนาดที่แท้จริงที่ระบุในคอลัมน์
รูปที่ 5 ขนาดที่แท้จริงที่ระบุในคอลัมน์

กำหนดช่องว่างระหว่างแถวและคอลัมน์

เมื่อกำหนดขนาดแทร็กตารางกริดแล้ว คุณสามารถแก้ไขช่องว่างตารางกริดเพื่อปรับแต่งระยะห่างระหว่างแทร็กได้ คุณสามารถระบุช่องว่างระหว่างคอลัมน์ด้วยฟังก์ชัน columnGap และช่องว่างระหว่างแถวด้วย rowGap ในตัวอย่างต่อไปนี้ มีช่องว่าง 16dp ระหว่างแต่ละแถว และช่องว่าง 8dp ระหว่างแต่ละคอลัมน์ (รูปที่ 5)

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
        rowGap(16.dp)
        columnGap(8.dp)
    }
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

ช่องว่างระหว่างแถวและคอลัมน์
รูปที่ 6 ช่องว่างระหว่างแถวและคอลัมน์

นอกจากนี้ คุณยังใช้ฟังก์ชันอำนวยความสะดวก gap เพื่อกำหนดช่องว่างของคอลัมน์และแถวที่มีขนาดเท่ากัน รวมถึงกำหนดขนาดคอลัมน์และช่องว่างแยกกันโดยใช้ฟังก์ชันเดียวได้ด้วย โค้ดต่อไปนี้จะเพิ่มช่องว่าง 8dp ช่องลงในตารางกริด

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
        gap(8.dp) // Equivalent to columnGap(8.dp) and rowGap(8.dp)
    }
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

กำหนดพื้นที่ตารางกริดด้วยพื้นที่ที่มีชื่อ

พื้นที่ที่มีชื่อช่วยให้คุณแนบชื่อกับกลุ่มเซลล์ตารางกริดได้ ซึ่งเรียกว่าพื้นที่ตารางกริด คุณสามารถใช้ชื่อเหล่านี้แทนดัชนีพิกัดเมื่อวางองค์ประกอบ UI ในตารางกริด

การใช้พื้นที่ที่มีชื่อมีประโยชน์หลัก 2 ประการต่อความสามารถในการอ่านโค้ด ดังนี้

  • เมื่อกำหนดเลย์เอาต์ตารางกริด วัตถุประสงค์และตำแหน่งของเนื้อหาที่คาดหวังจะชัดเจน
  • เมื่อเพิ่มเนื้อหา วัตถุประสงค์ของเนื้อหานั้นต้องชัดเจน

หากต้องการจัดระเบียบเลย์เอาต์ที่ซับซ้อนอย่างชัดเจน คุณสามารถแยกโครงสร้างตารางกริดจริงออกจากการวางตำแหน่งย่อยได้โดยการกำหนดพื้นที่ตารางกริดเชิงความหมาย

ภายในแลมบ์ดา config ให้ใช้ฟังก์ชัน area ใน GridConfigurationScope เพื่อลงทะเบียนพื้นที่ที่มีชื่อในตารางกริด จากนั้นคุณสามารถกำหนด Composable ย่อยให้กับพื้นที่เหล่านี้ได้โดยใช้ตัวแก้ไข gridItem กับตัวระบุพื้นที่ที่เกี่ยวข้อง ฟังก์ชัน area จะจับคู่ตัวระบุเชิงความหมาย (เช่น ค่าคลาส enum หรือคีย์สตริง) กับชุดพิกัดตารางกริดจริง เส้นตารางและดัชนีจะอิงตาม 1 (นั่นคือ แถวแรกคือ 1 และคอลัมน์แรกคือ 1)

เช่น คุณกำหนดตารางกริดที่มีรหัสพื้นที่ 4 รายการ ดังนี้

/**
 * An enum representing the IDs for named areas within the grid.
 */
enum class GridAreaNames {
    Area1,
    Area2,
    Area3,
    Area4
}

ระบุชื่อพื้นที่โดยใช้พารามิเตอร์ areaId พร้อมกับพิกัดและช่วงของเซลล์ของพื้นที่ ตัวแก้ไข gridItem ใช้ areaId เป็นคีย์เพื่อกำหนดรายการย่อยแต่ละรายการให้กับพื้นที่ตารางกริดที่กำหนดไว้ ดังที่แสดงในตัวอย่างต่อไปนี้

Grid(
    config = {
        // Define a single column that takes all available width.
        repeat(2) { column(0.5f) }

        // Define four rows, each taking 25% of the total height.
        repeat(4) { row(0.25f) }

        // Define named grid areas by associating an areaId with specific row and column indices.
        // Row and column indices are 1-based.
        area(areaId = GridAreaNames.Area1, row = 1, column = 1, columnSpan = 2)
        area(areaId = GridAreaNames.Area2, row = 2, column = 1, rowSpan = 3)
        area(areaId = GridAreaNames.Area3, rows = 2..3, columns = 2..2)
        area(areaId = GridAreaNames.Area4, row = 4, column = 2)

        gap(4.dp)
    },
    modifier = Modifier.size(360.dp)
) {
    PastelRedCard(
        "Area 1",
        // Use Modifier.gridItem(areaId) to place this composable into the
        // grid area defined with the matching ID in the config block.
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area1)
    )
    PastelGreenCard(
        "Area 2",
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area2)
    )
    PastelBlueCard(
        "Area 3",
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area3)
    )
    PastelYellowCard(
        "Area 4",
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area4)
    )
}

การใช้พื้นที่ที่มีชื่อช่วยให้คุณจัดระเบียบหรือปรับตารางเลย์เอาต์ทางกายภาพ (เช่น การเปลี่ยนแถว คอลัมน์ หรือขนาดแทร็ก) ในแลมบ์ดา config ได้โดยไม่ต้องแก้ไขลำดับหรือพารามิเตอร์ของ Composable ย่อย