修复了 Jetpack Compose 中 LazyColumn 内的网格?
Posted
技术标签:
【中文标题】修复了 Jetpack Compose 中 LazyColumn 内的网格?【英文标题】:Fixed Grid inside LazyColumn in Jetpack Compose? 【发布时间】:2021-11-19 00:13:58 【问题描述】:目前在 Jetpack Compose 中,此代码会引发 IllegalStateException
,因为您不能嵌套两个垂直滚动的 Composable:
@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)
)
我不希望网格本身滚动,而只是显示我传递给它的 Composable 的固定网格。在LazyColumn
中显示非滚动网格是否有任何解决方法?
【问题讨论】:
【参考方案1】:如果您不介意使用不稳定的 API,您可以使用 LazyVerticalGrid
并使用 span
参数使 item
占据整个宽度,如 @Mustafa pointed out:
LazyVerticalGrid(
cells = GridCells.Fixed(spanCount),
)
item(
span = GridItemSpan(spanCount)
)
Text("Title")
items(10)
Text(it.toString())
稳定之前是recommended
使用
LazyColumn
和Row
等稳定组件来实现相同的结果。
可以通过实现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)
)
【讨论】:
我正在寻找一种在 LazyColumn 中实现 LazyVerticalGrid 的方法,这是完美的解决方案。 这个解决方案在你有一个小的数据列表和简单的网格项目 UI 的情况下可以正常工作,但是当你的数据很大并且网格的项目有一个复杂的 UI 和状态时,它会变得滞后和重。 @MustafaIbrahim 您是否尝试过运行该应用程序的发布版本?LazyColumn
在调试中的性能要差得多。您是否也尝试过具有相同布局的普通单格LazyColumn
?我不认为我的方法比普通的LazyColumn
增加了太多开销
@MustafaIbrahim LazyVerticalGrid
自 1.2.* 以来的性能应该比我的解决方案更好,因为它是使用 LazyColumn
重写的,但在 1.1.* b> 我希望性能大致相同。【参考方案2】:
如果您有少量数据列表和简单的网格项目 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 */
【讨论】:
以上是关于修复了 Jetpack Compose 中 LazyColumn 内的网格?的主要内容,如果未能解决你的问题,请参考以下文章
viewpager jetpack compose 中的垂直滚动不起作用
Jetpack compose 更新到 1.0.0-rc01 后无法预览
Jetpack All In Compose ?看各种Jetpack库在Compose中的使用
Jetpack-Compose 学习笔记—— Compose 布局你学会了么?