FlowRow
và FlowColumn
là các thành phần kết hợp tương tự như Row
và Column
, nhưng khác ở các mục đó
chuyển sang dòng tiếp theo khi vùng chứa hết không gian. Thao tác này sẽ tạo nhiều hàng hoặc cột. Bạn cũng có thể kiểm soát số lượng mục trong một hàng
bằng cách đặt maxItemsInEachRow
hoặc maxItemsInEachColumn
. Bạn thường có thể sử dụng
FlowRow
và FlowColumn
để tạo bố cục thích ứng – nội dung sẽ không bị cắt
nếu các mục quá lớn cho một kích thước và sử dụng kết hợp
maxItemsInEach*
với Modifier.weight(weight)
có thể giúp tạo bố cục
lấp đầy/mở rộng chiều rộng của hàng hoặc cột khi cần.
Ví dụ điển hình là cho một khối hoặc giao diện người dùng lọc:
Cách sử dụng cơ bản
Để sử dụng FlowRow
hoặc FlowColumn
, hãy tạo các thành phần kết hợp này và đặt các mục
bên trong lớp đó phải tuân theo luồng tiêu chuẩn:
@Composable private fun FlowRowSimpleUsageExample() { FlowRow(modifier = Modifier.padding(8.dp)) { ChipItem("Price: High to Low") ChipItem("Avg rating: 4+") ChipItem("Free breakfast") ChipItem("Free cancellation") ChipItem("£50 pn") } }
Đoạn mã này dẫn đến giao diện người dùng hiển thị ở trên, với các mục tự động chuyển đến hàng tiếp theo khi không còn chỗ trong hàng đầu tiên.
Tính năng của bố cục luồng
Bố cục flow có các tính năng và thuộc tính mà bạn có thể sử dụng để tạo nhiều bố cục khác nhau trong ứng dụng của mình.
Cách sắp xếp trục chính: sắp xếp theo chiều ngang hoặc chiều dọc
Trục chính là trục mà các mục được bố trí (ví dụ: trong
FlowRow
, các mục được sắp xếp theo chiều ngang). Tham số horizontalArrangement
trong FlowRow
kiểm soát cách phân bổ không gian trống giữa các mục.
Bảng sau đây cho thấy các ví dụ về cách đặt horizontalArrangement
trên các mục cho FlowRow
:
Đã đặt chế độ sắp xếp theo chiều ngang trên |
Kết quả |
|
|
Đối với FlowColumn
, có các lựa chọn tương tự cho verticalArrangement
, với
giá trị mặc định là Arrangement.Top
.
Sắp xếp trên trục chéo
Trục chéo là trục ngược với trục chính. Để
ví dụ: trong FlowRow
, đây là trục tung. Để thay đổi cách
nội dung bên trong vùng chứa được sắp xếp theo trục chéo, hãy sử dụng
verticalArrangement
cho FlowRow
và horizontalArrangement
cho
FlowColumn
.
Đối với FlowRow
, bảng sau đây trình bày ví dụ về cách thiết lập các chế độ cài đặt khác nhau
verticalArrangement
cho các mặt hàng:
Chế độ sắp xếp theo chiều dọc được đặt trên |
Kết quả |
|
|
Đối với FlowColumn
, bạn có thể sử dụng các lựa chọn tương tự cho horizontalArrangement
.
Bố cục trục chéo mặc định là Arrangement.Start
.
Căn chỉnh từng mục riêng lẻ
Bạn có thể muốn đặt các mục riêng lẻ trong hàng bằng các vị trí khác nhau
căn chỉnh. Điều này khác với verticalArrangement
và
horizontalArrangement
vì chế độ này sẽ căn chỉnh các mục trong dòng hiện tại. Bạn có thể
áp dụng phương thức này bằng Modifier.align()
.
Ví dụ: khi các mục trong FlowRow
có chiều cao khác nhau, hàng này sẽ lấy giá trị
chiều cao của mục lớn nhất và áp dụng Modifier.align(alignmentOption)
cho
mục:
Đã đặt căn chỉnh theo chiều dọc trên |
Kết quả |
|
|
Đối với FlowColumn
, bạn có thể sử dụng các lựa chọn tương tự. Căn chỉnh mặc định là
Alignment.Start
.
Số mục tối đa trong hàng hoặc cột
Tham số maxItemsInEachRow
hoặc maxItemsInEachColumn
xác định giá trị tối đa
các mục trong trục chính để cho phép trong một dòng trước khi xuống dòng tiếp theo. Chiến lược phát hành đĩa đơn
mặc định là Int.MAX_INT
, cho phép nhiều mục nhất có thể, miễn là
kích thước của chúng cho vừa với đường kẻ.
Ví dụ: việc đặt maxItemsInEachRow
sẽ buộc bố cục ban đầu chỉ
có 3 mục:
Chưa đặt giới hạn tối đa |
|
Tải từng phần các mục trong luồng
ContextualFlowRow
và ContextualFlowColumn
là sự kiện chuyên biệt
phiên bản FlowRow
và FlowColumn
cho phép bạn tải từng phần nội dung
của hàng hoặc cột luồng. Các thuộc tính này cũng cung cấp thông tin về vị trí của mục (chỉ mục, số hàng và kích thước có sẵn), chẳng hạn như liệu mục có nằm trong hàng đầu tiên hay không. Điều này rất hữu ích cho các tập dữ liệu lớn và nếu bạn cần thông tin theo ngữ cảnh
về một mặt hàng.
Tham số maxLines
giới hạn số hàng hiển thị, còn overflow
tham số chỉ định nội dung nào sẽ được hiển thị khi tràn các mục
đã truy cập, cho phép bạn chỉ định expandIndicator
tuỳ chỉnh hoặc
collapseIndicator
.
Ví dụ: để hiển thị "+ (số mục còn lại)" hoặc "Ẩn bớt" nút:
val totalCount = 40 var maxLines by remember { mutableStateOf(2) } val moreOrCollapseIndicator = @Composable { scope: ContextualFlowRowOverflowScope -> val remainingItems = totalCount - scope.shownItemCount ChipItem(if (remainingItems == 0) "Less" else "+$remainingItems", onClick = { if (remainingItems == 0) { maxLines = 2 } else { maxLines += 5 } }) } ContextualFlowRow( modifier = Modifier .safeDrawingPadding() .fillMaxWidth(1f) .padding(16.dp) .wrapContentHeight(align = Alignment.Top) .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(4.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), maxLines = maxLines, overflow = ContextualFlowRowOverflow.expandOrCollapseIndicator( minRowsToShowCollapse = 4, expandIndicator = moreOrCollapseIndicator, collapseIndicator = moreOrCollapseIndicator ), itemCount = totalCount ) { index -> ChipItem("Item $index") }
Trọng lượng mặt hàng
Trọng số sẽ tăng trọng số của một mục dựa trên hệ số của nó và không gian có sẵn trên dòng mục đó
đã được đặt ở đâu. Điều quan trọng là có sự khác biệt giữa FlowRow
và Row
về cách sử dụng trọng số để tính chiều rộng của một mục. Đối với Rows
, trọng số
dựa trên tất cả các mục trong Row
. Với FlowRow
, trọng số được dựa trên
mục trong dòng mà một mục được đặt vào, không phải tất cả các mục trong
Vùng chứa FlowRow
.
Ví dụ: nếu bạn có 4 mục cùng nằm trên một dòng, mỗi mục có các giá trị khác nhau
trọng số là 1f, 2f, 1f
và 3f
, thì tổng trọng lượng là 7f
. Dung lượng còn lại
trong một hàng hoặc cột sẽ được chia cho 7f
. Sau đó, chiều rộng của mỗi mục sẽ được tính bằng: weight * (remainingSpace / totalWeight)
.
Bạn có thể sử dụng kết hợp Modifier.weight
và các mục tối đa với FlowRow
hoặc FlowColumn
để tạo bố cục giống như lưới. Phương pháp này rất hữu ích khi tạo
bố cục thích ứng điều chỉnh theo kích thước thiết bị của bạn.
Sau đây là một số ví dụ về những gì bạn có thể đạt được khi sử dụng trọng số. Ví dụ: một lưới có các mục có kích thước bằng nhau, như minh hoạ dưới đây:
Để tạo lưới có kích thước mục bằng nhau, bạn có thể làm như sau:
val rows = 3 val columns = 3 FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = rows ) { val itemModifier = Modifier .padding(4.dp) .height(80.dp) .weight(1f) .clip(RoundedCornerShape(8.dp)) .background(MaterialColors.Blue200) repeat(rows * columns) { Spacer(modifier = itemModifier) } }
Quan trọng là nếu bạn thêm một mục khác và lặp lại 10 lần thay vì 9 lần,
mục cuối cùng chiếm toàn bộ cột cuối cùng, làm tổng trọng số của toàn bộ hàng
là 1f
:
Bạn có thể kết hợp trọng số với Modifiers
khác, chẳng hạn như
Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio)
hoặc
Modifier.fillMaxWidth(fraction)
. Tất cả các đối tượng sửa đổi này hoạt động cùng với
cho phép định cỡ thích ứng các mục trong FlowRow
(hoặc FlowColumn
).
Bạn cũng có thể tạo một lưới xen kẽ gồm các kích thước mục khác nhau, trong đó có hai mục chiếm một nửa chiều rộng của từng mục và một mục chiếm toàn bộ chiều rộng của mục tiếp theo cột:
Bạn có thể thực hiện điều này bằng mã sau:
FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = 2 ) { val itemModifier = Modifier .padding(4.dp) .height(80.dp) .clip(RoundedCornerShape(8.dp)) .background(Color.Blue) repeat(6) { item -> // if the item is the third item, don't use weight modifier, but rather fillMaxWidth if ((item + 1) % 3 == 0) { Spacer(modifier = itemModifier.fillMaxWidth()) } else { Spacer(modifier = itemModifier.weight(0.5f)) } } }
Định cỡ phân số
Bằng cách sử dụng Modifier.fillMaxWidth(fraction)
, bạn có thể chỉ định kích thước của phần tử
vùng chứa mà một mục sẽ chiếm dụng. Điều này khác với cách
Modifier.fillMaxWidth(fraction)
hoạt động khi áp dụng cho Row
hoặc Column
, theo
các mục Row/Column
chiếm tỷ lệ phần trăm chiều rộng còn lại, thay vì
chiều rộng của toàn bộ vùng chứa.
Ví dụ: đoạn mã sau đây tạo ra kết quả khác khi sử dụng FlowRow
so với Row
:
FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = 3 ) { val itemModifier = Modifier .clip(RoundedCornerShape(8.dp)) Box( modifier = itemModifier .height(200.dp) .width(60.dp) .background(Color.Red) ) Box( modifier = itemModifier .height(200.dp) .fillMaxWidth(0.7f) .background(Color.Blue) ) Box( modifier = itemModifier .height(200.dp) .weight(1f) .background(Color.Magenta) ) }
|
|
|
fillMaxColumnWidth()
và fillMaxRowHeight()
Áp dụng Modifier.fillMaxColumnWidth()
hoặc
Modifier.fillMaxRowHeight()
với một mục bên trong FlowColumn
hoặc FlowRow
đảm bảo rằng các mục trong cùng một cột hoặc hàng có cùng chiều rộng hoặc chiều cao với
mục lớn nhất trong cột/hàng.
Ví dụ: ví dụ này sử dụng FlowColumn
để hiển thị danh sách các món tráng miệng Android. Bạn có thể thấy sự khác biệt về chiều rộng của từng mục khi
Modifier.fillMaxColumnWidth()
được áp dụng cho các mục so với khi không áp dụng và
các mục xuống dòng.
FlowColumn( Modifier .padding(20.dp) .fillMaxHeight() .fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp), maxItemsInEachColumn = 5, ) { repeat(listDesserts.size) { Box( Modifier .fillMaxColumnWidth() .border(1.dp, Color.DarkGray, RoundedCornerShape(8.dp)) .padding(8.dp) ) { Text( text = listDesserts[it], fontSize = 18.sp, modifier = Modifier.padding(3.dp) ) } } }
Đã áp dụng |
|
Chưa đặt thay đổi chiều rộng nào (gói các mục) |
Đề xuất cho bạn
- Lưu ý: văn bản có đường liên kết sẽ hiện khi JavaScript tắt
- Kiến thức cơ bản về bố cục Compose
- ConstraintLayout trong Compose
- Các thao tác trên trình chỉnh sửa {:#editor- actions}