我读过类似的话题,但没有得到令人满意的结果:
我的用例是:来创建一个注释列表(数百个条目),并可能显示对每个注释的答复(每个条目有数百个条目)。
目前,不可能在另一个LazyColumn中执行嵌套LazyColumn,因为Compose将引发异常:
java.lang.IllegalStateException:垂直滚动组件的测量带有无限大的最大高度约束,这是不允许的。一个常见的原因是嵌套布局,如LazyColumn和Column(Modifier.verticalScroll())。如果要在项目列表之前添加标题,请在LazyColumn范围内的主项()之前添加一个标头作为单独的项()。这种情况还可能有其他原因:您的ComposeView被添加到具有一定权重的LinearLayout中,您应用了Modifier.wrapContentSize(un界= true)或编写了自定义布局。请尝试删除滚动容器上方层次结构中无限约束的来源。
以上链接(以及我所想到的其他链接)提供的解决方案是:
LazyColumn -我不能使用它,因为每个项目可以有不同的高度(例如:单行和多行注释)。LazyColumn中使用普通的LazyColumn(而不是惰性的)--从性能上看,它不如懒惰的,当使用Android的Profiler和500个元素列表时,普通Column会在我的应用程序中使用350 my的内存,而使用惰性的Composables则使用220-240 my的内存。因此,它将无法正确回收。FlowColumn --我没有看到这个和普通的Column之间的任何性能差异,所以请看上面。LazyColumn的滚动使用新增加的组成1.2.0 userScrollEnabled参数-不幸的是,它引发了相同的错误,这是一种预期的行为(参见这里)。LazyColumn的.height()参数,如wrapContentHeight()或使用IntrinsicSize.Min -相同的错误。还有其他解决办法吗?特别是考虑到这可以在不限制高度的情况下将懒惰的组件嵌套在苹果的SwiftUI中。
发布于 2022-09-30 10:53:55
我有一个类似的用例,而且我有一个LazyColumn的解决方案,这个解决方案对我来说很好,而且性能也很好,我的想法是将数据作为一个具有不同类型元素的大型LazyColumn来处理。因为评论回复现在是单独的列表项,所以您必须首先将数据扁平化,这样它才是一个大列表或多个列表。现在,对于子注释,您只需在前面添加一些填充内容,否则它们将显示为单独的惰性项。我还使用了LazyVerticalGrid而不是LazyColumn,因为我必须在最后显示一个画廊图片网格,您可能不需要这样做,但是如果需要,您必须在任何其他地方使用span选项,如下所示。
你会得到这样的东西:
LazyVerticalGrid(
modifier = Modifier
.padding(6.dp),
columns = GridCells.Fixed(3)
) {
item(span = { GridItemSpan(3) }) {
ComposableTitle()
}
items(
items = flattenedCommentList,
key = { it.commentId },
span = { GridItemSpan(3) }) { comment ->
ShowCommentComposable(comment)
//here subcomments will have extra padding in front
}
item(span = { GridItemSpan(3) }) {
ComposableGalleryTitle()
}
items(items = imageGalleryList,
key = { it.imageId }) { image ->
ShowImageInsideGrid(image) //images in 3 column grid
}
}发布于 2022-09-26 03:33:28
我用这个函数解决了这个问题
@Composable
fun NestedLazyList(
modifier: Modifier = Modifier,
outerState: LazyListState = rememberLazyListState(),
innerState: LazyListState = rememberLazyListState(),
outerContent: LazyListScope.() -> Unit,
innerContent: LazyListScope.() -> Unit,
) {
val scope = rememberCoroutineScope()
val innerFirstVisibleItemIndex by remember {
derivedStateOf {
innerState.firstVisibleItemIndex
}
}
SideEffect {
if (outerState.layoutInfo.visibleItemsInfo.size == 2 && innerState.layoutInfo.totalItemsCount == 0)
scope.launch { outerState.scrollToItem(outerState.layoutInfo.totalItemsCount) }
println("outer ${outerState.layoutInfo.visibleItemsInfo.map { it.index }}")
println("inner ${innerState.layoutInfo.visibleItemsInfo.map { it.index }}")
}
BoxWithConstraints(
modifier = modifier
.scrollable(
state = rememberScrollableState {
scope.launch {
val toDown = it <= 0
if (toDown) {
if (outerState.run { firstVisibleItemIndex == layoutInfo.totalItemsCount - 1 }) {
Log.i(TAG, "NestedLazyList: down inner")
innerState.scrollBy(-it)
} else {
Log.i(TAG, "NestedLazyList: down outer")
outerState.scrollBy(-it)
}
} else {
if (innerFirstVisibleItemIndex == 0 && innerState.firstVisibleItemScrollOffset == 0) {
Log.i(TAG, "NestedLazyList: up outer")
outerState.scrollBy(-it)
} else {
Log.i(TAG, "NestedLazyList: up inner")
innerState.scrollBy(-it)
}
}
}
it
},
Orientation.Vertical,
)
) {
LazyColumn(
userScrollEnabled = false,
state = outerState,
modifier = Modifier
.heightIn(maxHeight)
) {
outerContent()
item {
LazyColumn(
state = innerState,
userScrollEnabled = false,
modifier = Modifier
.height(maxHeight)
) {
innerContent()
}
}
}
}
}我所做的就是:
首先,我使用lazyList将内部BoxWithConstraints的高度设置为父视图的高度,这允许内部列表填充屏幕,而不需要扩展懒散的概念。
然后,我通过禁用惰性滚动来控制滚动,并使父滚动可以确定滚动何时影响父列表以及子滚动何时应滚动。
在父级更改时,这仍然存在一些bud,在我的例子中,我使用了这个SideEffect。
发布于 2022-10-13 19:06:46
根列可以使用rememberScrollState()。就像这样;
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())) {
LazyColumn {
// your code
}
LazyRow {
// your code
}
}https://stackoverflow.com/questions/72271130
复制相似问题