【问题标题】:Jetpack Compose Vertical Grid single item span sizeJetpack Compose Vertical Grid 单项跨度大小
【发布时间】:2021-09-29 19:42:11
【问题描述】:
在 xml 中,您可以在 GridLayoutManager 中使用 GridLayoutManager.SpanSizeLookup 设置单个项目的跨度大小(该项目将在行中使用多少列,例如,在 3 列的网格中,我可以将第一项设置为跨度大小为 3,因此它将使用网格的所有宽度),但在 Compose 中我找不到这样做的方法,垂直网格只有一种设置全局跨度计数和添加项目的方法,但没有设置单个项目的跨度大小,有没有办法做到这一点?
【问题讨论】:
标签:
android
android-jetpack-compose
android-jetpack-compose-list
【解决方案1】:
目前没有开箱即用的支持。我现在解决这个问题的方法是使用 LazyColumn 然后项目是 Rows 并且在每个 Row 中,您可以使用 weight 决定项目的宽度。
我已经实现,在我的例子中,我有标题(全宽)和等宽项目的单元格(根据屏幕的宽度,每行可能有 1、2 或 3 个单元格)。这是一种解决方法,但在VerticalGrid 提供本机支持之前,这是一个选项。
My solution is here - 查找 LazyListScope 扩展。
【解决方案2】:
Jetpack Compose 版本 1.1.0-beta03 将水平跨度引入 LazyVerticalGrid。
示例代码:
val list by remember { mutableStateOf(listOf("A", "E", "I", "O", "U")) }
LazyVerticalGrid(
cells = GridCells.Fixed(2)
) {
// Spanned Item:
item(
span = {
// Replace "maxCurrentLineSpan" with the number of spans this item should take.
// Use "maxCurrentLineSpan" if you want to take full width.
GridItemSpan(maxCurrentLineSpan)
}
) {
Text("Vowels")
}
// Other items:
items(list) { item ->
Text(item)
}
}
【解决方案3】:
根据答案改编代码,我创建了一个更“通用”的方法,它可以与 Adaptive 和 Fixed 一起使用,我是 Compose 的新手,所以我接受建议
@Composable
fun HeaderGrid(cells: GridCells, content: HeaderGridScope.() -> Unit) {
var columns = 1
var minColumnWidth = 0.dp
when (cells) {
is GridCells.Fixed -> {
columns = cells.count
minColumnWidth = cells.minSize
}
is GridCells.Adaptive -> {
val width = LocalContext.current.resources.displayMetrics.widthPixels
val columnWidthPx = with(LocalDensity.current) { cells.minSize.toPx() }
minColumnWidth = cells.minSize
columns = ((width / columnWidthPx).toInt()).coerceAtLeast(1)
}
}
LazyColumn(modifier = Modifier.fillMaxWidth()){
content(HeaderGridScope(columns, minColumnWidth, this))
}
}
fun <T>HeaderGridScope.gridItems(items: List<T>, content: @Composable (T) -> Unit) {
items.chunked(numColumn).forEach {
listScope.item {
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
it.forEach {
content(it)
}
if (it.size < numColumn) {
repeat(numColumn - it.size) {
Spacer(modifier = Modifier.width(columnWidth))
}
}
}
}
}
}
fun HeaderGridScope.header(content: @Composable BoxScope.() -> Unit) {
listScope.item {
Box(
modifier = Modifier
.fillMaxWidth(),
content = content
)
}
}
data class HeaderGridScope(val numColumn: Int, val columnWidth: Dp, val listScope: LazyListScope)
sealed class GridCells {
class Fixed(val count: Int, val minSize: Dp) : GridCells()
class Adaptive(val minSize: Dp) : GridCells()
}