Bố cục thẻ cổ điển dạng rộng có lưới

biểu tượng xếp hạng 4 sao

Nguyên tắc thiết kế ứng dụng truyền hình xác định một biến thể thẻ có tên là Thẻ cổ điển dạng rộng, hiển thị hình ảnh và khối nội dung mô tả của hình ảnh đó cạnh nhau. Khi tạo bố cục hai chiều phức tạp cho màn hình TV, việc sử dụng tính năng định vị dựa trên toạ độ truyền thống hoặc các vùng chứa RowColumn được lồng sâu có thể khiến mã của bạn khó đọc, duy trì và tái cấu trúc. Thẻ cổ điển có chiều rộng là một trường hợp sử dụng lý tưởng cho API Grid của Jetpack Compose, giúp bạn sắp xếp các phần tử cạnh nhau một cách rõ ràng bằng cách sử dụng các vùng bố cục 2D do người dùng xác định, mang tính ngữ nghĩa.

Quy cách của thành phần thẻ Cổ điển dạng rộng cho thấy 5 vùng bố cục có tên: Hình ảnh, Tiêu đề, Phụ đề, Nội dung mô tả và Văn bản bổ sung.
Hình 1. Thẻ cổ điển có chiều rộng lớn với 5 vùng được đặt tên: Vùng hình ảnh và 4 vùng văn bản trong khối nội dung.

Các phương pháp hay nhất

Triển khai bố cục thẻ bằng Grid. Việc sử dụng vùng chứa Grid giúp cải thiện khả năng đọc mã bằng cách tách các phương diện bố cục thực tế khỏi vị trí của mục con. Thay vì dựa vào chỉ mục chính xác của các đường kẻ, hãy xác định các vùng được đặt tên theo ngữ nghĩa bằng hàm area và đặt các thành phần kết hợp con bằng đối tượng sửa đổi gridItem. Kết hợp tính năng điều chỉnh kích thước linh hoạt của các đường kẻ, chẳng hạn như GridTrackSize.Autominmax(0.dp, 1.fr), với khoảng cách chính xác giữa các đường kẻ (gap(row = 8.dp, column = 16.dp)) để sắp xếp các thành phần thẻ phức tạp cạnh nhau một cách rõ ràng và mạnh mẽ.

Nguyên liệu

  • Grid: Bố cục vùng chứa 2D trong Jetpack Compose, sắp xếp các thành phần kết hợp con thành hàng và cột dựa trên một lambda cấu hình
  • gridItem: Một tiện ích Modifier liên kết một phần tử con trên giao diện người dùng với một areaId cụ thể có tên bên trong bố cục Grid
  • area: Một hàm DSL cấu hình trong GridConfigurationScope giúp ánh xạ một areaId ngữ nghĩa đến các khoảng hoặc dải ô hàng và cột cụ thể
  • Card: Một thành phần kết hợp vùng chứa Material Design nhóm các phần tử và kiểu giao diện người dùng có liên quan
  • GridTrackSize.MinMax: Một thuộc tính định cỡ của đường kẻ xác định ranh giới linh hoạt (minmax) cho kích thước hàng hoặc cột
  • GridTrackSize.Auto: Một thuộc tính định cỡ của bản nhạc tự động định cỡ bản nhạc hàng hoặc cột để phù hợp với nội dung của bản nhạc (column(GridTrackSize.Auto))
  • gap: Một hàm cấu hình chỉ định khoảng cách dọc (row) và khoảng cách ngang (column) giữa các đường lưới

Các bước

Xác định mã nhận dạng khu vực, định cấu hình các vùng và đường lưới, sau đó đặt các thành phần kết hợp con.

1. Xác định mã nhận dạng khu vực ngữ nghĩa

Trước tiên, hãy tạo một bản trình bày an toàn về kiểu của các vùng bên trong bố cục thẻ Cổ điển rộng. Lớp enum giúp tránh lỗi chính tả chuỗi và đảm bảo an toàn trong thời gian biên dịch khi ánh xạ các bản nhạc và đặt các mục con.

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

2. Định cấu hình các kênh lưới 2D và khu vực được đặt tên

Bên trong lambda config của thành phần kết hợp Grid, hãy xác định các cột và hàng tạo nên cấu trúc thẻ. Sử dụng GridTrackSize.Auto cho cột hình ảnh để bao bọc chiều rộng hình thu nhỏ một cách gọn gàng. Sử dụng minmax(0.dp, 1.fr) cho cột nội dung để cột này mở rộng linh hoạt theo chiều rộng còn lại của thẻ. Chỉ định khoảng cách giữa các bản nhạc bằng gap(row = 8.dp, column = 16.dp). Liên kết các giá trị nhận dạng CardArea với toạ độ đường đua thực tế bằng hàm 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. Đặt các thành phần kết hợp con bằng đối tượng sửa đổi gridItem

Sau khi định cấu hình các đường và khu vực, hãy đặt từng phần tử con trên giao diện người dùng chỉ bằng ý định ngữ nghĩa bằng cách sử dụng đối tượng sửa đổi gridItem. Bạn có thể khai báo các thành phần kết hợp con theo bất kỳ thứ tự nào. Vùng chứa Grid tự động định vị từng phần tử trực tiếp vào vùng 2D được chỉ định.

@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),
            )
        }
    }
}

Kết quả

Bằng cách sắp xếp thẻ Wide classic bằng Grid và các vùng được đặt tên, bạn sẽ tách biệt rõ ràng giữa các đường bố cục thực, toạ độ vùng và vị trí thành phần kết hợp con. Cấu trúc này giúp bố cục của bạn dễ đọc và duy trì trong khi tuân theo nguyên tắc thiết kế ứng dụng truyền hình cho các thành phần hình thu nhỏ và nội dung mô tả song song.

Tài nguyên khác