Jetpack Compose:如何将 LazyVerticalGrid 放入可滚动列中?

Kes*_*ker 50 android kotlin android-jetpack-compose

当尝试将 a 放入可滚动LazyVerticalGrid内容时,出现以下错误: Column

java.lang.IllegalStateException:不允许在同一方向嵌套可滚动布局,例如 LazyColumn 和 Column(Modifier.verticalScroll())。如果您想在项目列表之前添加标题,请查看 LazyColumn 组件,该组件具有 DSL api,允许首先通过 item() 函数添加标题,然后通过 items() 添加项目列表。

我不是在制作传统的列表,我只是有很多太大而无法在屏幕上显示的元素。因此,我希望该列滚动,以便我可以看到所有元素。这是我的代码:

@ExperimentalFoundationApi
@Composable
fun ProfileComposable(id: String?) {
    val viewModel: ProfileViewModel = viewModel()
    if (id != null) {
        viewModel.getProfile(id)
        val profile = viewModel.profile.value
        val scrollState = rememberScrollState()
        if (profile != null) {
            Column(modifier = Modifier
                .fillMaxWidth()
                .fillMaxHeight()
                .verticalScroll(scrollState)) {
                Row() {
                    ProfilePic(profile.getImgUrl(), profile.name)
                    Column(Modifier.padding(16.dp)) {
                        ProfileName(profile.name)
                        Stats(profile.stats) //      <--------------- the offending composable
                    }
                }
                Sprites(sprites = profile.sprites)
                TextStat(profile.id.toString(), "Pokemon Number")
                TextStat(profile.species.name, "Species")
                TextStat(profile.types.joinToString { it.type.name }, "Types")
                TextStat(profile.weight.toString(), "Weight")
                TextStat(profile.forms.joinToString { it.name }, "Forms")
            }
        } else {
            Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                CircularProgressIndicator()
            }
        }
    } else {
        Text("Error")
    }
} 
Run Code Online (Sandbox Code Playgroud)

可组合项Stats()包含LazyVerticalGrid导致错误的内容:

@ExperimentalFoundationApi
@Composable
fun Stats(stats: List<Stat>) {
    LazyVerticalGrid(cells = GridCells.Fixed(2)) {
        itemsIndexed(stats) { index, item ->
            StatBox(stat = item)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我不希望网格滚动,我只想在可滚动列中显示网格。

Moh*_*eza 29

我有一个类似的用例,目标是设计一个个人资料屏幕,顶部有一堆信息和统计数据,然后以屏幕​​底部的网格形式显示帖子。

我最终对整个列表使用 LazyVerticalGrid 并为需要填充整个屏幕的项目设置完整跨度:

LazyVerticalGrid(cells = GridCells.Fixed(3)) {
    item(span = { GridItemSpan(3) }) { TopInfo() }
    item(span = { GridItemSpan(3) }) { SomeOtherInfo() }
    item(span = { GridItemSpan(3) }) { BottomInfo() }
    items(gridItems) { GridItemView(it) }
}
Run Code Online (Sandbox Code Playgroud)

  • 可以使用“maxCurrentLineSpan”代替“GridItemSpan(3)” (6认同)

Jai*_*bin 14

我自己刚刚遇到了这个问题。正如 @gaohomway 所说,最好的选择是使用 Google 的Accompanist 库中的实验性 FlowRow() 。

这是一个工作代码片段作为示例:

@Composable
fun ProfileScreen2() {
    LazyColumn(
        modifier = Modifier
            .fillMaxSize()
    ) {
        item {
            Box(modifier = Modifier.fillMaxWidth().height(200.dp).background(color = Red))
        }

        item {
            Box(modifier = Modifier.fillMaxWidth().height(200.dp).background(color = Gray))
        }

        item {
            FlowRow() {
                SampleContent()
            }
        }
    }
}

@Composable
internal fun SampleContent() {
    repeat(60) {
        Box(
            modifier = Modifier
                .size(64.dp)
                .background(Blue)
                .border(width = 1.dp, color = DarkGray),
            contentAlignment = Alignment.Center,
        ) {
            Text(it.toString())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

显示此可滚动页面(不要介意底部的导航栏):

  • 如果存在大型数据集,FlowRow 会出现性能问题。 (2认同)

小智 11

尝试使用LazyVerticalGrid的精确高度,它对我有用:

@ExperimentalFoundationApi
@Composable
fun Stats(stats: List<Stat>) {
   LazyVerticalGrid(columns = GridCells.Fixed(2),
    modifier = Modifier.height(50.dp)) {
    itemsIndexed(stats) { index, item ->
        StatBox(stat = item)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

与Thracian\'s 答案类似,但使用nestedScroll\xef\xbc\x8c 因为当项目数超过 8 时,它将默认滚动到内部 LazyLazyVerticalGrid

\n
@Preview(showBackground = true)\n@Composable\nprivate fun Test() {\n    val outState = rememberScrollState()\n    Column(\n        modifier = Modifier\n            .fillMaxSize()\n            .verticalScroll(outState)\n    ) {\n        Box(\n            modifier = Modifier\n                .fillMaxWidth()\n                .height(200.dp)\n                .background(Color.Red)\n        )\n\n        Stats(\n            modifier = Modifier\n                .heightIn(max = 1000.dp)\n                .nestedScroll(connection = object : NestedScrollConnection {\n                    override fun onPreScroll(\n                        available: Offset,\n                        source: NestedScrollSource\n                    ): Offset {\n                        if (outState.canScrollForward && available.y < 0) {\n                            val consumed = outState.dispatchRawDelta(-available.y)\n                            return Offset(x = 0f, y = -consumed)\n                        }\n                        return Offset.Zero\n                    }\n                }),\n            stats = List(500) { it }\n        )\n    }\n}\n\n@Composable\nfun Stats(\n    modifier: Modifier = Modifier,\n    stats: List<Int>\n) {\n    LazyVerticalGrid(\n        modifier = modifier,\n        columns = GridCells.Fixed(2)\n    ) {\n\n        itemsIndexed(stats) { index, item ->\n            Box(\n                modifier = Modifier.aspectRatio(1f),\n                contentAlignment = Alignment.Center\n            ) {\n                Text("Item $index")\n            }\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n


gao*_*way 3

原因

不允许在相同方向的布局中嵌套可滚动的布局,例如 LazyColumn 和 Column(Modifier.verticalScroll())。

LazyVerticalGrid暂时找不到禁止滚动的地方

备择方案

Android 官方Jetpack Compose Flow Layouts的替代库

FlowRow {
    // row contents
}

FlowColumn {
    // column contents
}

Run Code Online (Sandbox Code Playgroud)