Jetpack Compose Vertical Grid 单项跨度大小
Jetpack Compose Vertical Grid single item span size
在 xml 中,您可以在 GridLayoutManager 中使用 GridLayoutManager.SpanSizeLookup 来设置单个项目的跨度大小(项目将在行中使用多少列,例如,在 3 的网格中列我可以将第一个项目设置为跨度大小 3,这样它将使用网格的所有宽度),但是在 Compose 中我找不到方法,垂直网格只能设置全局跨度计数并添加项目,但不设置单个项目的跨度大小,有没有办法做到这一点?
目前不支持开箱即用。我现在解决这个问题的方法是使用 LazyColumn
然后项目是 Row
s 并且在每个 Row
中你可以决定一个项目的宽度,使用 weight
.
我已经实现了,在我的例子中,我有 headers(全宽)和等宽项目的单元格(根据屏幕的宽度,每个单元格可能有 1、2 或 3 个排)。这是一种解决方法,但在 VerticalGrid
提供本机支持之前,这是一个选项。
My solution is here - 查找 LazyListScope
扩展名。
根据答案改编代码,我创建了一个更“通用”的方法,它可以与 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()
}
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)
}
}
在 xml 中,您可以在 GridLayoutManager 中使用 GridLayoutManager.SpanSizeLookup 来设置单个项目的跨度大小(项目将在行中使用多少列,例如,在 3 的网格中列我可以将第一个项目设置为跨度大小 3,这样它将使用网格的所有宽度),但是在 Compose 中我找不到方法,垂直网格只能设置全局跨度计数并添加项目,但不设置单个项目的跨度大小,有没有办法做到这一点?
目前不支持开箱即用。我现在解决这个问题的方法是使用 LazyColumn
然后项目是 Row
s 并且在每个 Row
中你可以决定一个项目的宽度,使用 weight
.
我已经实现了,在我的例子中,我有 headers(全宽)和等宽项目的单元格(根据屏幕的宽度,每个单元格可能有 1、2 或 3 个排)。这是一种解决方法,但在 VerticalGrid
提供本机支持之前,这是一个选项。
My solution is here - 查找 LazyListScope
扩展名。
根据答案改编代码,我创建了一个更“通用”的方法,它可以与 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()
}
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)
}
}