简体   繁体   English

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

[英]Jetpack Compose: How to put a LazyVerticalGrid inside a scrollable Column?

When trying to put a LazyVerticalGrid inside a scrollable Column I get the following error:尝试将LazyVerticalGrid放入可滚动Column中时,出现以下错误:

java.lang.IllegalStateException: Nesting scrollable in the same direction layouts like LazyColumn and Column(Modifier.verticalScroll()) is not allowed. java.lang.IllegalStateException:不允许在 LazyColumn 和 Column(Modifier.verticalScroll()) 等相同方向布局中嵌套可滚动。 If you want to add a header before the list of items please take a look on LazyColumn component which has a DSL api which allows to first add a header via item() function and then the list of items via items().如果您想在项目列表之前添加 header,请查看具有 DSL api 的 LazyColumn 组件,它允许首先通过 item() function 添加 header,然后通过 items() 添加项目列表。

I am not making a traditional list, I just have alot of elements that are too big to fit on the screen.我不是在制作一个传统的列表,我只是有很多元素太大而无法显示在屏幕上。 Therefore I want the column to scroll so I can see all the elements.因此我希望该列滚动以便我可以看到所有元素。 Here is my code:这是我的代码:

@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")
    }
} 

The Stats() composable contains the LazyVerticalGrid which causes the error: Stats()可组合项包含导致错误的LazyVerticalGrid

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

I do not want the grid to scroll, I just want to display a grid within a scrollable column.我不想让网格滚动,我只想在可滚动的列中显示一个网格。

Reason原因

Nesting scrollable in the same direction layouts like LazyColumn and Column(Modifier.verticalScroll()) is not allowed.不允许在相同方向的布局中嵌套可滚动,例如 LazyColumn 和 Column(Modifier.verticalScroll())。

Can't find LazyVerticalGrid forbidden scrolling temporarily暂时找不到LazyVerticalGrid禁止滚动

Alternatives备择方案

Alternative library from Android official Jetpack Compose Flow Layouts Android 官方Jetpack Compose Flow Layouts的替代库

FlowRow {
    // row contents
}

FlowColumn {
    // column contents
}

I just ran into this problem myself.我自己也遇到了这个问题。 As @gaohomway said, your best bet is to use the experimental FlowRow() from Google's Accompanist library .正如@gaohomway 所说,您最好的选择是使用 Google 的Accompanist library中的实验性 FlowRow() 。

Here is a working code snippet as an example:以下是一个工作代码片段作为示例:

@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())
        }
    }
}

Displays this scrollable page (don't mind the nav bar at the bottom):显示此可滚动页面(不要介意底部的导航栏):

I had a similar use-case, the goal was to design a profile screen that has a bunch of information and statistics on top, and then comes to the posts as a Grid in the bottom of the screen.我有一个类似的用例,目标是设计一个个人资料屏幕,顶部有一堆信息和统计数据,然后在屏幕底部以网格的形式显示帖子。

I ended up using the LazyVerticalGrid for the whole list and setting full span for the items that need to fill the entire screen:我最终对整个列表使用了 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) }
}

try using exact height for LazyVerticalGrid , it worked for me:尝试使用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)
    }
  }
}

I ran into this same issue but in my case I just wanted to display 1-10 items with the same Composable component but different parameters, so I ended up creating a custom grid where you can pass:我遇到了同样的问题,但在我的例子中,我只想显示 1-10 个具有相同可组合组件但参数不同的项目,所以我最终创建了一个自定义网格,您可以在其中传递:

  1. List of composables可组合项列表
  2. number of desired items per row每行所需项目数
@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()
      }
    }
  }
}

Example on how to call:调用示例:

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

Might not be the best for performance and it's definitely not lazy but currently there is no non-lazy Grid for this purpose.可能不是最好的性能,它绝对不是懒惰的,但目前没有用于此目的的非惰性网格。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 jetpack compose 中使用 lazy column 和 lazyverticalgrid? - How can I use lazy column and lazyverticalgrid in jetpack compose? 有没有办法在 Jetpack Compose 的垂直可滚动视图中嵌套 LazyVerticalGrid - Is there a way to nest a LazyVerticalGrid iniside a vertical scrollable view in Jetpack Compose 如何使用带有 LazyVerticalGrid 的 jetpack 组合分页 - How to use jetpack compose paging with LazyVerticalGrid Jetpack Compose:如何在 LazyVerticalGrid 中将项目居中? - Jetpack Compose: How to center an item in LazyVerticalGrid? Jetpack Compose LazyVerticalGrid 口吃 - Jetpack Compose LazyVerticalGrid stuttering Jetpack Compose:带分数的可滚动列 - Jetpack Compose : Scrollable column with fractions LazyVerticalGrid 用于在 jetpack compose 中分页项目 - LazyVerticalGrid for paging items in jetpack compose 如何在 jetpack compose 中向 LazyVerticalGrid 添加一个 stickyHeader,例如 LazyColumn? - How can I add a stickyHeader to LazyVerticalGrid like LazyColumn in jetpack compose? 如何在 Jetpack Compose 中将列内的元素居中 - How to center elements inside a column in Jetpack Compose Jetpack Compose:带有verticalScroll修饰符的列中的LazyVerticalGrid抛出java.lang.IllegalStateException - Jetpack Compose:LazyVerticalGrid within Column with verticalScroll modifier throws java.lang.IllegalStateException
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM