Jetpack Compose 中的垂直嵌套滚动
Vertical nested scroll in Jetpack Compose
最近,我在使用 100% compose! 的应用程序中开发一项功能时撞墙了。我正在尝试实现垂直嵌套滚动视图。我的情况是我正在查看 edit/create 锻炼。这些被分成不同的组,里面有一个练习列表。
想法是有一个卡片列表,里面有一个项目(练习)列表()。
当我尝试构建视图时,出现了下一个错误:
java.lang.IllegalStateException: Nesting scrollable in the same direction layouts like ScrollableContainer and LazyColumn is not allowed. 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().
我知道它不受支持,我想问的是是否有任何我可以做的解决方法。代码如下所示:
LazyColumn(Modifier.fillMaxSize()) {
itemsIndexed(workout.workoutSets) { setIndex, workoutSet ->
//State that contains the re-order drag & drop and calls the original list to be modified in my VM
val state: ReorderableState = rememberReorderState(onMove = { from, to ->
Grove.e { "Moving from $from to $to" }
if (to <= workoutSet.exercises.lastIndex) {
onExerciseMoved(setIndex, from, to)
}
})
LazyColumn(
state = state.listState,
modifier = Modifier
.fillMaxWidth()
.reorderable(state) //Modifier that allows the drad&drop in this container
) {
itemsIndexed(items = workoutSet.exercises, itemContent = { index, item ->
Box(
Modifier
.fillMaxWidth()
.draggedItem(state.offset.takeIf { state.index == index }) //The dragged item modifier
.scale(if (state.index == null || state.index == index) 1f else .9f)
) {
CreatorExerciseItemRow(
onExerciseClick = { onExerciseClick(item) },
execution = item
)
}
})
}
}
}
您可以从库中找到我正在使用的拖放代码(不是我的)here。
最后让您了解我想要实现的目标。屏幕看起来像:
我的想法是,我可以 long-press 练习并将它们拖放到各自的卡片上。但同时允许屏幕变高并在需要时垂直滚动。现在,我只需将上面代码中的第一个 LazyColumn
替换为 repeat/foreach
即可正常工作。但是很快我的列表就变大了,视图被隐藏了。
您可以使用单个普通列表并根据类型绘制内容。
首先,您应该将数据转换为一个简单的列表(当然,这是一个伪代码)。
val plainList = mutableListOf<Any>()
worksets.forEach {
plainList.add(it)
it.exercises.forEach{
plainList.add(it)
}
}
然后,在您的 LazyColumn
中,您根据项目类型绘制项目。
LazyColumn(Modifier.fillMaxSize()) {
items(plainList) { item ->
when (item) {
is Workset -> WorkSetHeaderItem(item)
is Exercise -> ExerciseItem(item)
}
}
}
恐怕不可能。
据我了解,您可以限制在不同集合之间移动的项目。
您可以获取 ComposeReorderable
的源代码并为您的任务应用所需的更改。代码不多(我喜欢编写),所以应该不会太难。完成后甚至可以提交拉取请求,因为这样的功能可能对其他人有用。
最近,我在使用 100% compose! 的应用程序中开发一项功能时撞墙了。我正在尝试实现垂直嵌套滚动视图。我的情况是我正在查看 edit/create 锻炼。这些被分成不同的组,里面有一个练习列表。
想法是有一个卡片列表,里面有一个项目(练习)列表(
当我尝试构建视图时,出现了下一个错误:
java.lang.IllegalStateException: Nesting scrollable in the same direction layouts like ScrollableContainer and LazyColumn is not allowed. 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().
我知道它不受支持,我想问的是是否有任何我可以做的解决方法。代码如下所示:
LazyColumn(Modifier.fillMaxSize()) {
itemsIndexed(workout.workoutSets) { setIndex, workoutSet ->
//State that contains the re-order drag & drop and calls the original list to be modified in my VM
val state: ReorderableState = rememberReorderState(onMove = { from, to ->
Grove.e { "Moving from $from to $to" }
if (to <= workoutSet.exercises.lastIndex) {
onExerciseMoved(setIndex, from, to)
}
})
LazyColumn(
state = state.listState,
modifier = Modifier
.fillMaxWidth()
.reorderable(state) //Modifier that allows the drad&drop in this container
) {
itemsIndexed(items = workoutSet.exercises, itemContent = { index, item ->
Box(
Modifier
.fillMaxWidth()
.draggedItem(state.offset.takeIf { state.index == index }) //The dragged item modifier
.scale(if (state.index == null || state.index == index) 1f else .9f)
) {
CreatorExerciseItemRow(
onExerciseClick = { onExerciseClick(item) },
execution = item
)
}
})
}
}
}
您可以从库中找到我正在使用的拖放代码(不是我的)here。
最后让您了解我想要实现的目标。屏幕看起来像:
我的想法是,我可以 long-press 练习并将它们拖放到各自的卡片上。但同时允许屏幕变高并在需要时垂直滚动。现在,我只需将上面代码中的第一个 LazyColumn
替换为 repeat/foreach
即可正常工作。但是很快我的列表就变大了,视图被隐藏了。
您可以使用单个普通列表并根据类型绘制内容。
首先,您应该将数据转换为一个简单的列表(当然,这是一个伪代码)。
val plainList = mutableListOf<Any>()
worksets.forEach {
plainList.add(it)
it.exercises.forEach{
plainList.add(it)
}
}
然后,在您的 LazyColumn
中,您根据项目类型绘制项目。
LazyColumn(Modifier.fillMaxSize()) {
items(plainList) { item ->
when (item) {
is Workset -> WorkSetHeaderItem(item)
is Exercise -> ExerciseItem(item)
}
}
}
恐怕不可能。
据我了解,您可以限制在不同集合之间移动的项目。
您可以获取 ComposeReorderable
的源代码并为您的任务应用所需的更改。代码不多(我喜欢编写),所以应该不会太难。完成后甚至可以提交拉取请求,因为这样的功能可能对其他人有用。