Jetpack Compose 的 LazyVerticalGrid 是否有跨度策略

Does Jetpack Compose's LazyVerticalGrid have span strategy

我有一个包含 2 个单元格的 LazyVerticalGrid。

LazyVerticalGrid(
    cells = GridCells.Fixed(2),
    content = {
        items(moviePagingItems.itemCount) { index ->
            val movie = moviePagingItems[index] ?: return@items
            MovieItem(movie, Modifier.preferredHeight(320.dp))
        }
        renderLoading(moviePagingItems.loadState)
    }
)

我正在尝试使用 LazyGridScopefillParentMaxSize 修饰符显示全宽加载。

fun LazyGridScope.renderLoading(loadState: CombinedLoadStates) {
  when {
    loadState.refresh is LoadState.Loading -> {
        item {
            LoadingColumn("Fetching movies", Modifier.fillParentMaxSize())
        }
    }
    loadState.append is LoadState.Loading -> {
        item {
            LoadingRow(title = "Fetching more movies")
        }
    }
  }
}

但是因为我们有2个单元格,所以加载可以占据屏幕的一半。像这样:

有没有办法让我的加载视图占据整个宽度?

试试这样的:

var cellState by remember { mutableStateOf(2) }
LazyVerticalGrid(
    cells = GridCells.Fixed(cellState),
    content = {
        items(moviePagingItems.itemCount) { index ->
            val movie = moviePagingItems[index] ?: return@items
            MovieItem(movie, Modifier.preferredHeight(320.dp))
        }
        renderLoading(moviePagingItems.loadState) {
            cellState = it
        }
    }
)

renderLoading函数:

fun LazyGridScope.renderLoading(loadState: CombinedLoadStates, span: (Int) -> Unit) {
    when {
        loadState.refresh is LoadState.Loading -> {
            item {
                LoadingColumn("Fetching movies", Modifier.fillParentMaxSize())
            }
            span(1)
        }
        ...
        else -> span(2)
    }
  
}

我已经为它创建了一个问题:https://issuetracker.google.com/u/1/issues/176758183

我目前的解决方法是使用 LazyColumn 并实施项目或 header。

override val content: @Composable () -> Unit = {
    LazyColumn(
            contentPadding = PaddingValues(8.dp),
            content = {
                items(colors.chunked(3), itemContent = {

                    Row(horizontalArrangement = Arrangement.SpaceEvenly) {
                        val modifier = Modifier.weight(1f)
                        it.forEach {
                            ColorItem(modifier, it)
                        }
                        for (i in 1..(3 - it.size)) {
                            Spacer(modifier)
                        }
                    }
                })
                item {
                    Text(
                            text = stringResource(R.string.themed_colors),
                            style = MaterialTheme.typography.h3
                    )
                }
                items(themedColors.chunked(3), itemContent = {
                    Row(horizontalArrangement = Arrangement.SpaceEvenly) {
                        val modifier = Modifier.weight(1f)
                        it.forEach {
                            ColorItem(modifier, it)
                        }
                        for (i in 1..(3 - it.size)) {
                            Spacer(modifier)
                        }
                    }
                })
            })
}

Jetpack Compose 1.1.0-beta03 版本包括对 LazyVerticalGrid 的水平跨度支持。

这是示例用法:

private const val CELL_COUNT = 2

private val span: (LazyGridItemSpanScope) -> GridItemSpan = { GridItemSpan(CELL_COUNT) }

LazyVerticalGrid(
    cells = GridCells.Fixed(CELL_COUNT),
    content = {
        items(moviePagingItems.itemCount) { index ->
            val movie = moviePagingItems.peek(index) ?: return@items
            Movie(movie)
        }
        renderLoading(moviePagingItems.loadState)
    }
}

private fun LazyGridScope.renderLoading(loadState: CombinedLoadStates) {
    if (loadState.append !is LoadState.Loading) return

    item(span = span) {
        val title = stringResource(R.string.fetching_more_movies)
        LoadingRow(title = title)
    }
}

此答案的代码示例可在以下位置找到:Jetflix/MoviesGrid.kt