ade*_*111 47 android kotlin android-recyclerview android-jetpack-compose android-jetpack-compose-list
我读过类似的主题,但找不到满意的结果:
我的用例是:创建一个评论列表(数百个项目),并可以显示对每个评论的回复(每个项目数百个项目)。
目前不可能LazyColumn在另一个内部进行嵌套LazyColumn,因为 Compose 会抛出异常:
java.lang.IllegalStateException:垂直可滚动组件是用无限最大高度约束测量的,这是不允许的。常见原因之一是嵌套布局,例如 LazyColumn 和 Column(Modifier.verticalScroll())。如果您想在项目列表之前添加标题,请在 LazyColumn 范围内的主 items() 之前添加一个标题作为单独的 item() 。发生这种情况可能还有其他原因:您的 ComposeView 被添加到具有一定权重的 LinearLayout 中、您应用了 Modifier.wrapContentSize(unbounded = true) 或编写了自定义布局。请尝试消除滚动容器上方层次结构中无限约束的来源。
上面的链接(以及我想到的其他链接)提供的解决方案是:
LazyColumn- 我无法使用它,因为每个项目可以有不同的高度(例如:单行注释与多行注释)。Columns (不是惰性)LazyColumn- 性能方面它不如惰性,当使用 Android Studio 的 Profiler 和 500 个元素的列表时,正常Column会在我的应用程序中使用 350MB 的 RAM,而使用惰性 则需要 220-240MB Composables。因此它无法正常回收。FlowColumn伴奏者 - 我没有看到这个和正常之间有任何性能差异,Column所以请参见上面。LazyColumn滚动- 不幸的是,它会引发相同的错误,并且这是预期的行为(请参阅此处)。 userScrollEnabledLazyColumn参数.height(),如wrapContentHeight()或 using IntrinsicSize.Min- 相同的错误。还有其他想法如何解决这个问题吗?特别是考虑到可以在 Apple 的 SwiftUI 中嵌套惰性组件而无需限制高度。
我有一个类似的用例,并且我有一个解决方案,该解决方案LazyColumn对我来说效果很好且性能良好,其想法是将您的数据视为具有LazyColumn不同类型元素的大型数据。由于评论回复现在是单独的列表项,因此您必须首先展平数据,使其成为一个大列表或多个列表。现在,对于子注释,您只需在前面添加一些填充,否则它们将显示为单独的惰性项目。我还使用了 aLazyVerticalGrid而不是 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
}
}
Run Code Online (Sandbox Code Playgroud)
小智 -1
我在这个函数中解决了这个问题
@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()
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我所做的就是:
首先,我使用 ,将内部lazyList的高度设置为父视图的高度BoxWithConstraints,这让内部列表填充屏幕,而不会破坏lazy概念。
然后,我通过禁用延迟滚动来控制滚动,并使父级可滚动,以确定滚动何时影响父级列表以及子级何时应滚动。
芽,当父尺寸改变时,这仍然有一些错误,在我的例子中,我逃脱了这个SideEffect
| 归档时间: |
|
| 查看次数: |
23408 次 |
| 最近记录: |