[英]How can I use lazy column and lazyverticalgrid in jetpack compose?
[英]Jetpack Compose: How to put a LazyVerticalGrid inside a scrollable Column?
尝试将LazyVerticalGrid
放入可滚动Column
中时,出现以下错误:
java.lang.IllegalStateException:不允许在 LazyColumn 和 Column(Modifier.verticalScroll()) 等相同方向布局中嵌套可滚动。 如果您想在项目列表之前添加 header,请查看具有 DSL api 的 LazyColumn 组件,它允许首先通过 item() function 添加 header,然后通过 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)
}
}
}
我不想让网格滚动,我只想在可滚动的列中显示一个网格。
原因
不允许在相同方向的布局中嵌套可滚动,例如 LazyColumn 和 Column(Modifier.verticalScroll())。
暂时找不到LazyVerticalGrid
禁止滚动
备择方案
Android 官方Jetpack Compose Flow Layouts的替代库
FlowRow {
// row contents
}
FlowColumn {
// column contents
}
我自己也遇到了这个问题。 正如@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())
}
}
}
显示此可滚动页面(不要介意底部的导航栏):
我有一个类似的用例,目标是设计一个个人资料屏幕,顶部有一堆信息和统计数据,然后在屏幕底部以网格的形式显示帖子。
我最终对整个列表使用了 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) }
}
尝试使用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)
}
}
}
我遇到了同样的问题,但在我的例子中,我只想显示 1-10 个具有相同可组合组件但参数不同的项目,所以我最终创建了一个自定义网格,您可以在其中传递:
@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
)
可能不是最好的性能,它绝对不是懒惰的,但目前没有用于此目的的非惰性网格。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.