修复了 Jetpack Compose 中 LazyColumn 内的网格?
Fixed Grid inside LazyColumn in Jetpack Compose?
目前在 Jetpack Compose 中,此代码会抛出一个 IllegalStateException
,因为您无法嵌套两个垂直滚动的可组合项:
@ExperimentalFoundationApi
@Composable
fun MyLazyColumn() {
LazyColumn {
item {
Text(text = "My LazyColumn Title")
}
item {
LazyVerticalGrid(cells = GridCells.Fixed(4)) {
items(10) {
Box(
modifier = Modifier
.size(50.dp)
.padding(5.dp)
.background(Color.Gray)
)
}
}
}
}
}
我不希望网格本身滚动,而只是显示我传入其中的可组合项的固定网格。在 LazyColumn
中显示非滚动网格是否有任何解决方法?
如果你不介意使用不稳定的API,你可以使用LazyVerticalGrid
并使用span
参数让item
取全宽,如@穆斯塔法 :
LazyVerticalGrid(
cells = GridCells.Fixed(spanCount),
) {
item(
span = { GridItemSpan(spanCount) }
) {
Text("Title")
}
items(10) {
Text(it.toString())
}
}
稳定之前,就是recommended
using stable components like LazyColumn
and Row
to achieve the same result.
可以通过实施 gridItems
与 LazyColumn
一起使用来完成。
fun LazyListScope.gridItems(
count: Int,
nColumns: Int,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
itemContent: @Composable BoxScope.(Int) -> Unit,
) {
gridItems(
data = List(count) { it },
nColumns = nColumns,
horizontalArrangement = horizontalArrangement,
itemContent = itemContent,
)
}
fun <T> LazyListScope.gridItems(
data: List<T>,
nColumns: Int,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
key: ((item: T) -> Any)? = null,
itemContent: @Composable BoxScope.(T) -> Unit,
) {
val rows = if (data.isEmpty()) 0 else 1 + (data.count() - 1) / nColumns
items(rows) { rowIndex ->
Row(horizontalArrangement = horizontalArrangement) {
for (columnIndex in 0 until nColumns) {
val itemIndex = rowIndex * nColumns + columnIndex
if (itemIndex < data.count()) {
val item = data[itemIndex]
androidx.compose.runtime.key(key?.invoke(item)) {
Box(
modifier = Modifier.weight(1f, fill = true),
propagateMinConstraints = true
) {
itemContent.invoke(this, item)
}
}
} else {
Spacer(Modifier.weight(1f, fill = true))
}
}
}
}
}
用法:
LazyColumn {
item {
Text(text = "My LazyColumn Title")
}
// with count
gridItems(10, nColumns = 4) { index ->
Box(
modifier = Modifier
.size(50.dp)
.padding(5.dp)
.background(Color.Gray)
)
}
// or with list of items
gridItems(listOf(1,2,3), nColumns = 4) { item ->
Box(
modifier = Modifier
.size(50.dp)
.padding(5.dp)
.background(Color.Gray)
)
}
}
如果您的数据列表较小且网格项目简单 UI,但当您的数据很大且网格项目具有复杂的 UI 时,这个被接受的答案很好并且工作正常和状态,它会变得迟钝和沉重。
在我的例子中,我设法通过将 LazyVerticalGrid 作为网格项目和其他内容的容器来解决这个问题,现在它看起来像这样:
val spanCount = 2
LazyVerticalGrid(
modifier = modifier
.fillMaxWidth(),
cells = GridCells.Fixed(spanCount),
state = rememberLazyGridState(),
) {
item(
span = {
/** Take a full row */
GridItemSpan(currentLineSpan = spanCount)
}
) {
Column(
modifier = Modifier.fillMaxWidth()
) {
items.forEach {
/** Iterate over your items here */
}
}
}
items(
items = gridItems
){gridItem->
/** Grid items go here */
}
}
对我来说,我已经明确地添加了高度,它对我在 lazy colum 中的 LazyverticalGrid 工作得很好
LazyVerticalGrid(
cells = GridCells.Fixed(3),
contentPadding = PaddingValues(5.dp),
modifier = Modifier
.layoutId("lazy_list")
.height(200.dp)
目前在 Jetpack Compose 中,此代码会抛出一个 IllegalStateException
,因为您无法嵌套两个垂直滚动的可组合项:
@ExperimentalFoundationApi
@Composable
fun MyLazyColumn() {
LazyColumn {
item {
Text(text = "My LazyColumn Title")
}
item {
LazyVerticalGrid(cells = GridCells.Fixed(4)) {
items(10) {
Box(
modifier = Modifier
.size(50.dp)
.padding(5.dp)
.background(Color.Gray)
)
}
}
}
}
}
我不希望网格本身滚动,而只是显示我传入其中的可组合项的固定网格。在 LazyColumn
中显示非滚动网格是否有任何解决方法?
如果你不介意使用不稳定的API,你可以使用LazyVerticalGrid
并使用span
参数让item
取全宽,如@穆斯塔法
LazyVerticalGrid(
cells = GridCells.Fixed(spanCount),
) {
item(
span = { GridItemSpan(spanCount) }
) {
Text("Title")
}
items(10) {
Text(it.toString())
}
}
稳定之前,就是recommended
using stable components like
LazyColumn
andRow
to achieve the same result.
可以通过实施 gridItems
与 LazyColumn
一起使用来完成。
fun LazyListScope.gridItems(
count: Int,
nColumns: Int,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
itemContent: @Composable BoxScope.(Int) -> Unit,
) {
gridItems(
data = List(count) { it },
nColumns = nColumns,
horizontalArrangement = horizontalArrangement,
itemContent = itemContent,
)
}
fun <T> LazyListScope.gridItems(
data: List<T>,
nColumns: Int,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
key: ((item: T) -> Any)? = null,
itemContent: @Composable BoxScope.(T) -> Unit,
) {
val rows = if (data.isEmpty()) 0 else 1 + (data.count() - 1) / nColumns
items(rows) { rowIndex ->
Row(horizontalArrangement = horizontalArrangement) {
for (columnIndex in 0 until nColumns) {
val itemIndex = rowIndex * nColumns + columnIndex
if (itemIndex < data.count()) {
val item = data[itemIndex]
androidx.compose.runtime.key(key?.invoke(item)) {
Box(
modifier = Modifier.weight(1f, fill = true),
propagateMinConstraints = true
) {
itemContent.invoke(this, item)
}
}
} else {
Spacer(Modifier.weight(1f, fill = true))
}
}
}
}
}
用法:
LazyColumn {
item {
Text(text = "My LazyColumn Title")
}
// with count
gridItems(10, nColumns = 4) { index ->
Box(
modifier = Modifier
.size(50.dp)
.padding(5.dp)
.background(Color.Gray)
)
}
// or with list of items
gridItems(listOf(1,2,3), nColumns = 4) { item ->
Box(
modifier = Modifier
.size(50.dp)
.padding(5.dp)
.background(Color.Gray)
)
}
}
如果您的数据列表较小且网格项目简单 UI,但当您的数据很大且网格项目具有复杂的 UI 时,这个被接受的答案很好并且工作正常和状态,它会变得迟钝和沉重。
在我的例子中,我设法通过将 LazyVerticalGrid 作为网格项目和其他内容的容器来解决这个问题,现在它看起来像这样:
val spanCount = 2
LazyVerticalGrid(
modifier = modifier
.fillMaxWidth(),
cells = GridCells.Fixed(spanCount),
state = rememberLazyGridState(),
) {
item(
span = {
/** Take a full row */
GridItemSpan(currentLineSpan = spanCount)
}
) {
Column(
modifier = Modifier.fillMaxWidth()
) {
items.forEach {
/** Iterate over your items here */
}
}
}
items(
items = gridItems
){gridItem->
/** Grid items go here */
}
}
对我来说,我已经明确地添加了高度,它对我在 lazy colum 中的 LazyverticalGrid 工作得很好
LazyVerticalGrid(
cells = GridCells.Fixed(3),
contentPadding = PaddingValues(5.dp),
modifier = Modifier
.layoutId("lazy_list")
.height(200.dp)