android Jetpack组成:如何把一个LazyVerticalGrid放在一个可滚动的列中?

vc9ivgsu  于 2023-01-24  发布在  Android
关注(0)|答案(5)|浏览(436)

当尝试将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")
    }
}

Stats()可组合对象包含导致错误的LazyVerticalGrid

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

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

nhhxz33t

nhhxz33t1#

我有一个类似的用例,目标是设计一个配置文件屏幕,上面有一堆信息和统计数据,然后在屏幕底部的网格中显示帖子。
最后,我对整个列表使用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) }
}
8i9zcol2

8i9zcol22#

我自己也遇到过这个问题,正如@gaohomway所说,最好的办法是使用Google的Accompanist library中的实验性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())
        }
    }
}

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

x8goxv8g

x8goxv8g3#

原因

不允许嵌套在相同方向上可滚动的布局,如LazyColumn和Column(Modifier.verticalScroll())。
暂时找不到LazyVerticalGrid禁止滚动

备选办法

来自Android官方Jetpack Compose Flow Layouts的替代库

FlowRow {
    // row contents
}

FlowColumn {
    // column contents
}
w7t8yxp5

w7t8yxp54#

尝试对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)
    }
  }
}
c9x0cxw0

c9x0cxw05#

我遇到了同样的问题,但在我的例子中,我只想显示1-10个具有相同可组合组件但参数不同的项目,所以我最终创建了一个自定义网格,您可以在其中传递:
1.可组合列表
1.每行所需项目数

@Composable
fun VerticalGrid(composableList: List<@Composable () -> Unit>, itemsPerRow: Int) {
  val components = composableList.toMutableList()
  Column(Modifier.fillMaxWidth()) {
    while (components.isNotEmpty()) {
      val rowComponents: List<@Composable () -> Unit> = components.take(itemsPerRow)
      val listOfSpacers: List<@Composable () -> Unit> = listOfSpacers(itemsPerRow - rowComponents.size)
      RowWithItems(items = rowComponents.plus(listOfSpacers))
      components.removeAll(rowComponents)
    }
  }
}

private fun listOfSpacers(number: Int): List<@Composable () -> Unit> {
  val mutableList = emptyList<@Composable () -> Unit>().toMutableList()
  repeat(number) {
    mutableList.add { Spacer(Modifier) }
  }
  return mutableList.toList()
}

@Composable
private fun RowWithItems(items: List<@Composable () -> Unit>) {
  Row(Modifier.fillMaxWidth()) {
    items.forEach { item ->
      Box(Modifier.weight(1f)) {
        item()
      }
    }
  }
}

如何调用的示例:

VerticalGrid(
      composableList = listOf(
        { ProfileDataField(value = profileInfo.country.name) },
        { ProfileDataField(value = profileInfo.dateOfBirth) },
        { ProfileDataField(value = profileInfo.gender) }
      ),
      itemsPerRow = 2
    )

它可能不是性能最好的,也肯定不是懒惰的,但目前还没有非懒惰的网格可以实现这一目的。

相关问题