Đặt thuộc tính vùng chứa

Bạn có thể xác định cấu hình vùng chứa Lưới để tạo bố cục linh hoạt, phù hợp với nhiều kích thước màn hình và loại nội dung. Trang này mô tả cách thực hiện những việc sau:

Xác định lưới

Lưới bao gồm các cột và hàng. Thành phần kết hợp Grid có một tham số config chấp nhận một lambda để xác định các cột và hàng trong GridConfigurationScope. Ví dụ sau đây xác định một lưới có 3 hàng và 2 cột, mỗi hàng và cột có kích thước cố định được chỉ định trong Dp:

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

Đặt các mục vào lưới

Grid lấy các phần tử giao diện người dùng trong lambda content và đặt chúng vào các ô lưới. Lưới bố trí các mục bất kể bạn có xác định rõ ràng các hàng và cột hay không. Theo mặc định, Grid sẽ cố gắng đặt một phần tử trên giao diện người dùng vào ô lưới có sẵn trong hàng; nếu không được, phần tử này sẽ đặt phần tử đó vào một ô lưới có sẵn trong hàng tiếp theo. Nếu không có ô trống, Grid sẽ tạo một hàng mới.

Trong ví dụ sau, lưới có 6 ô lưới và đặt một thẻ vào mỗi ô (Hình 1). Mỗi ô lưới có kích thước 160dp x 90dp, tổng kích thước lưới là 320dp x 270dp.

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

6 thẻ được đặt trong một lưới có 3 hàng và 2 cột.
Hình 1. 6 thẻ được đặt trong một lưới có 3 hàng và 2 cột.

Để thay đổi hành vi mặc định này thành điền theo cột, hãy đặt thuộc tính flow thành 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()
}

Hàm luồng thay đổi hướng để đặt các mục.
Hình 2. GridFlow.Row (trái) và GridFlow.Column (phải).

Quản lý kích thước kênh

Hàng và cột được gọi chung là làn lưới. Bạn có thể chỉ định kích thước của một đường lưới bằng một trong các phương thức sau:

  • Cố định (Dp): Phân bổ một kích thước cụ thể (ví dụ: column(180.dp)).
  • Tỷ lệ phần trăm (Float): Phân bổ một tỷ lệ phần trăm trong tổng không gian có sẵn từ 0.0f đến 1.0f (ví dụ: row(0.5f) cho 50%).
  • Linh hoạt (Fr): Phân bổ không gian còn lại theo tỷ lệ sau khi tính toán các thành phần cố định và thành phần phần trăm. Ví dụ: nếu hai hàng được đặt thành 1.fr3.fr, thì hàng thứ hai sẽ nhận được 75% chiều cao còn lại.
  • Nội tại: Điều chỉnh kích thước của bản phụ đề dựa trên nội dung bên trong. Để biết thêm thông tin, hãy xem bài viết Xác định kích thước của các đường lưới một cách tự nhiên.

Ví dụ sau đây sử dụng các lựa chọn định cỡ đường chạy khác nhau để xác định chiều cao hàng:

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")

}

Chiều cao hàng được xác định bằng 4 lựa chọn chính về kích thước của các thành phần.
Hình 3. Chiều cao hàng được xác định bằng 4 lựa chọn chính về kích thước của các rãnh trong Grid.

Đặt kích thước tối thiểu cho các đường lưới linh hoạt

Khi vùng chứa lưới không còn khoảng trống, một thành phần linh hoạt tiêu chuẩn có thể thu nhỏ thành 0.dp. Để ngăn chặn điều này và đảm bảo nội dung không bị thu hẹp, hãy sử dụng GridTrackSize.MinMax để áp dụng kích thước tối thiểu rõ ràng trong khi vẫn giữ cho đường dẫn linh hoạt.

Ví dụ sau đây phân bổ ít nhất 100.dp cho hàng đầu tiên:

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)")
}

Chiều cao hàng được xác định bằng 4 lựa chọn chính về kích thước của các thành phần.
Hình 4. Hàng đầu tiên có chiều cao ít nhất là 100.dp.

Đặt kích thước tối thiểu của phần tử lưới để đặt danh sách tải từng phần

Các thành phần theo dõi linh hoạt tiêu chuẩn sẽ tự động truy vấn kích thước nội tại của các thành phần con để thiết lập kích thước cơ sở. Tuy nhiên, Jetpack Compose cấm truy vấn kích thước nội tại của SubcomposeLayout, hỗ trợ các thành phần, chẳng hạn như LazyColumnLazyRow.

Việc đặt một danh sách lazy bên trong một thành phần theo dõi linh hoạt tiêu chuẩn sẽ gây ra sự cố IllegalStateException. Để đặt danh sách tải từng phần một cách an toàn vào bên trong một ô lưới linh hoạt, hãy dùng MinMax với kích thước tối thiểu rõ ràng (chẳng hạn như 0.dp) để bỏ qua quá trình đo lường nội tại.

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("Lazy column 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")
        }
    }
}

Chiều cao hàng được xác định bằng 4 lựa chọn chính về kích thước của các thành phần.
Hình 5. LazyColumn trong một ô lưới.

Xác định kích thước đường lưới một cách tự nhiên

Bạn có thể sử dụng kích thước nội tại cho Grid khi muốn bố cục thích ứng với nội dung thay vì ép buộc nội dung vào một vùng chứa cố định. Kích thước của đường lưới được xác định bằng các giá trị sau:

  • GridTrackSize.MaxContent: Sử dụng kích thước nội tại tối đa của nội dung (ví dụ: chiều rộng được xác định bằng độ dài đầy đủ của văn bản trong một khối văn bản không có tính năng xuống dòng).
  • GridTrackSize.MinContent: Sử dụng kích thước tối thiểu vốn có của nội dung (ví dụ: chiều rộng được xác định bằng từ dài nhất trong một khối văn bản).
  • GridTrackSize.Auto: Sử dụng kích thước linh hoạt cho một bản nhạc thích ứng dựa trên không gian có sẵn. Theo mặc định, thành phần này hoạt động như MaxContent, nhưng sẽ thu nhỏ và bao bọc nội dung để vừa với vùng chứa mẹ.

Ví dụ sau đây đặt hai văn bản cạnh nhau. Kích thước cột cho văn bản đầu tiên được xác định bằng chiều rộng tối thiểu cần thiết để hiển thị văn bản, còn chiều rộng cột thứ hai phụ thuộc vào chiều rộng tối đa cần thiết của văn bản.

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.")
}

Kích thước nội tại được chỉ định trong các cột.
Hình 5. Kích thước nội tại được chỉ định trong các cột.

Đặt khoảng cách giữa các hàng và cột

Sau khi điều chỉnh kích thước các rãnh lưới, bạn có thể sửa đổi khoảng trống giữa các rãnh để tinh chỉnh khoảng cách giữa các rãnh. Bạn có thể chỉ định khoảng cách giữa các cột bằng hàm columnGap và khoảng cách giữa các hàng bằng rowGap. Trong ví dụ sau, có một khoảng trống 16dp giữa mỗi hàng và một khoảng trống 8dp giữa mỗi cột (Hình 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()
}

Khoảng trống giữa các hàng và cột.
Hình 6. Khoảng trống giữa các hàng và cột.

Bạn cũng có thể dùng hàm tiện ích gap để xác định khoảng trống có cùng kích thước cột và hàng, đồng thời xác định riêng kích thước cột và khoảng trống bằng một hàm duy nhất. Mã sau đây sẽ thêm khoảng trống 8dp vào lưới:

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()
}