เลย์เอาต์การ์ดคลาสสิกแบบกว้างพร้อมตารางกริด

ไอคอนคะแนน 4 ดาว

หลักเกณฑ์การออกแบบแอป TV กำหนดตัวแปรของการ์ด ที่เรียกว่าการ์ดคลาสสิกแบบกว้าง ซึ่งจะแสดงรูปภาพและบล็อกเนื้อหาคำอธิบายเคียงข้างกัน เมื่อสร้างเลย์เอาต์ 2 มิติที่ซับซ้อนสำหรับหน้าจอทีวี การใช้การจัดตำแหน่งแบบดั้งเดิมตามพิกัดหรือคอนเทนเนอร์ Row และ Column ที่ซ้อนกันหลายชั้นอาจทำให้โค้ดอ่าน แก้ไข และปรับโครงสร้างได้ยาก การ์ดคลาสสิกแบบกว้างเป็นกรณีการใช้งานที่เหมาะสำหรับ Jetpack Compose Grid API ซึ่งช่วยให้คุณจัดโครงสร้างองค์ประกอบเคียงข้างกันได้อย่างชัดเจนโดยใช้พื้นที่เลย์เอาต์ 2 มิติที่กำหนดโดยผู้ใช้และมีความหมาย

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

แนวทางปฏิบัติแนะนำ

ใช้ Grid เพื่อใช้เลย์เอาต์การ์ด การใช้คอนเทนเนอร์ Grid ช่วยให้โค้ดอ่านง่ายขึ้นด้วยการแยกขนาดเลย์เอาต์จริงออกจากการจัดวางรายการย่อย กำหนดพื้นที่ที่มีชื่อซึ่งมีความหมายด้วยฟังก์ชัน area และวางคอมโพสได้ย่อยด้วยตัวปรับแต่ง gridItem แทนที่จะใช้ดัชนีแทร็กที่แน่นอน รวมการปรับขนาดแทร็กที่ยืดหยุ่น เช่น GridTrackSize.Auto และ minmax(0.dp, 1.fr), เข้ากับช่องว่างแทร็กที่แน่นอน (gap(row = 8.dp, column = 16.dp)) เพื่อจัดระเบียบคอมโพเนนต์การ์ดที่ซับซ้อนซึ่งอยู่เคียงข้างกันอย่างชัดเจนและมีประสิทธิภาพ

ส่วนประกอบ

  • Grid: เลย์เอาต์คอนเทนเนอร์ 2 มิติใน Jetpack Compose ที่จัดเรียงคอมโพสได้ย่อยเป็นแถวและคอลัมน์ตามแลมบ์ดาการกำหนดค่า
  • gridItem: ส่วนขยาย Modifier ที่เชื่อมโยงองค์ประกอบ UI ย่อยกับ areaId ที่เฉพาะเจาะจงซึ่งมีชื่อภายในเลย์เอาต์ Grid
  • area: ฟังก์ชัน DSL การกำหนดค่าภายใน GridConfigurationScope ที่ แมป areaId ที่มีความหมายกับช่วงหรือช่วงของแถวและคอลัมน์ที่เฉพาะเจาะจง
  • Card: คอมโพสได้คอนเทนเนอร์ Material Design ที่จัดกลุ่มองค์ประกอบ UI และการจัดรูปแบบที่เกี่ยวข้อง
  • GridTrackSize.MinMax: พร็อพเพอร์ตี้การปรับขนาดแทร็กที่กำหนดขอบเขตที่ยืดหยุ่น (min และ max) สำหรับขนาดแถวหรือคอลัมน์
  • GridTrackSize.Auto: พร็อพเพอร์ตี้การปรับขนาดแทร็กที่ปรับขนาดแทร็กแถวหรือคอลัมน์ โดยอัตโนมัติให้พอดีกับเนื้อหา (column(GridTrackSize.Auto))
  • gap: ฟังก์ชันการกำหนดค่าที่ระบุระยะห่างแนวตั้ง (row) และแนวนอน (column) ระหว่างแทร็กตารางกริด

ขั้นตอน

กำหนดตัวระบุพื้นที่ กำหนดค่าแทร็กและพื้นที่ตารางกริด แล้ววางคอมโพสได้ย่อย

1. กำหนดตัวระบุพื้นที่ที่มีความหมาย

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

enum class CardArea {
    Image,
    Title,
    Subtitle,
    Description,
    ExtraText,
}

2. กำหนดค่าแทร็กตารางกริด 2 มิติและพื้นที่ที่มีชื่อ

กำหนดคอลัมน์และแถวที่ประกอบกันเป็นโครงสร้างการ์ดภายในแลมบ์ดา config ของคอมโพสได้ Grid ใช้ GridTrackSize.Auto สำหรับคอลัมน์รูปภาพเพื่อให้ครอบคลุมความกว้างของภาพขนาดย่อได้อย่างชัดเจน ใช้ minmax(0.dp, 1.fr) สำหรับคอลัมน์เนื้อหาเพื่อให้ขยายได้อย่างยืดหยุ่นตามความกว้างที่เหลือของการ์ด ระบุระยะห่างแทร็กด้วย gap(row = 8.dp, column = 16.dp) แมปตัวระบุ CardArea กับพิกัดแทร็กจริงโดยใช้ฟังก์ชัน area

Grid(
    config = {
        // Define columns: left column for image, right for content
        column(GridTrackSize.Auto)
        column(minmax(0.dp, 1.fr))

        // Define row tracks for the vertical content stack
        row(GridTrackSize.Auto)
        row(GridTrackSize.Auto)
        row(GridTrackSize.Auto)
        row(GridTrackSize.Auto)

        // Map semantic identifiers to grid coordinates and spans
        area(CardArea.Image, row = 1, column = 1, rowSpan = 4)
        area(CardArea.Title, row = 1, column = 2)
        area(CardArea.Subtitle, row = 2, column = 2)
        area(CardArea.Description, row = 3, column = 2)
        area(CardArea.ExtraText, row = 4, column = 2)

        gap(row = 8.dp, column = 16.dp)
    }
) {
    // Child elements placed in Step 3
}

3. วางคอมโพสได้ย่อยโดยใช้ตัวปรับแต่ง gridItem

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

@Composable
fun WideClassicCard(
    imageContent: @Composable () -> Unit,
    title: String,
    subtitle: String,
    description: String,
    extraText: String,
    modifier: Modifier = Modifier,
) {
    Card(modifier = modifier) {
        Grid(
            config = {
                // Define columns: left column for image, right for content
                column(GridTrackSize.Auto)
                column(minmax(0.dp, 1.fr))

                // Define row tracks for the vertical content stack
                row(GridTrackSize.Auto)
                row(GridTrackSize.Auto)
                row(GridTrackSize.Auto)
                row(GridTrackSize.Auto)

                // Map semantic identifiers to grid coordinates and spans
                area(CardArea.Image, row = 1, column = 1, rowSpan = 4)
                area(CardArea.Title, row = 1, column = 2)
                area(CardArea.Subtitle, row = 2, column = 2)
                area(CardArea.Description, row = 3, column = 2)
                area(CardArea.ExtraText, row = 4, column = 2)

                gap(row = 8.dp, column = 16.dp)
            },
        ) {
            Box(modifier = Modifier.gridItem(CardArea.Image)) {
                imageContent()
            }
            Text(
                text = title,
                style = MaterialTheme.typography.titleLarge,
                modifier = Modifier
                    .gridItem(CardArea.Title)
                    .padding(top = 16.dp, end = 16.dp),
            )

            Text(
                text = subtitle,
                style = MaterialTheme.typography.titleMedium,
                modifier = Modifier
                    .gridItem(CardArea.Subtitle)
                    .padding(end = 16.dp),
            )

            Text(
                text = description,
                style = MaterialTheme.typography.bodyMedium,
                modifier = Modifier
                    .gridItem(CardArea.Description)
                    .padding(end = 16.dp),
            )

            Text(
                text = extraText,
                style = MaterialTheme.typography.labelSmall,
                modifier = Modifier
                    .gridItem(CardArea.ExtraText)
                    .padding(bottom = 16.dp, end = 16.dp),
            )
        }
    }
}

ผลลัพธ์

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

แหล่งข้อมูลเพิ่มเติม