Jetpack compose 中的 [NestedScrollView + RecyclerView] 或 [Nested RecyclerView (Recycler inside another
Posted
技术标签:
【中文标题】Jetpack compose 中的 [NestedScrollView + RecyclerView] 或 [Nested RecyclerView (Recycler inside another recycler) 相当于啥【英文标题】:What is the equivalent of [NestedScrollView + RecyclerView] or [Nested RecyclerView (Recycler inside another recycler) in Jetpack composeJetpack compose 中的 [NestedScrollView + RecyclerView] 或 [Nested RecyclerView (Recycler inside another recycler) 相当于什么 【发布时间】:2021-06-28 16:49:27 【问题描述】:我想在 Jetpack compose 中创建以下布局。
我尝试在垂直可滚动框中创建两个列表,但这是不可能的,因为我得到了这个错误: “java.lang.IllegalStateException:不允许在同一方向上嵌套可滚动布局,如 ScrollableContainer 和 LazyColumn。如果您想在项目列表之前添加标题,请查看 LazyColumn 组件,该组件具有 DSL api,它允许首先通过 item() 函数添加标题,然后通过 items() 添加项目列表。"
我尝试使用以下代码在父列表中创建两个不同的列表,但这也不起作用。
@Composable
fun MainList()
LazyColumn()
item
/* LazyRow code here */
item
/* LazyColumn code here */
现在我不知道我还能尝试在同一个活动上实现两个列表(一个垂直和一个水平)并保持活动垂直滚动。
【问题讨论】:
【参考方案1】:我认为最好的选择是 LazyVerticalGrid
允许对每个项目进行某种扩展逻辑,但看起来它尚不受支持(beta-03)。
所以我将把我的解决方案留在这里,对整个列表使用一个LazyColumn
,对“我的书”部分使用LazyRow
。
LazyColumn(
modifier = Modifier.fillMaxSize(),
)
// My Books section
item
Column(modifier = Modifier.fillMaxWidth())
Text("My Books")
LazyRow
items(books) item ->
// Each Item
// Whishlisted Books title
item
Text("Whishlisted Books", style = MaterialTheme.typography.h4)
// Turning the list in a list of lists of two elements each
items(wishlisted.windowed(2, 2, true)) item ->
Row
// Draw item[0]
// Draw item[1]
这是我的gist with the full solution,结果如下所示。
【讨论】:
非常感谢您花时间写详细的回复。它就像一个魅力:) Flow 似乎比通过 XML 制作视图要容易得多,这太疯狂了......【参考方案2】:你可以这样做:
Column(Modifier.fillMaxWidth())
LazyRow()
items(itemsList)
//.....
LazyColumn()
items(itemsList2)
//..
或:
Column(Modifier.fillMaxWidth())
LazyRow()
items(itemsList)
//....
LazyVerticalGrid(cells = GridCells.Fixed(2))
items(itemsList2.size)
//....
【讨论】:
非常感谢您抽出宝贵时间提供详细的解决方案。虽然解决方案是准确的,但它不会滚动整个活动。因此,我将合并您(网格部分)和@nglauber 提供的解决方案。再次感谢。 快速提问:既然这里的 LazyVerticalGrid 被包裹在一个简单的 Column 中,你是否还能获得 LazyVerticalGrid 的回收优势?或者 Column 会在第一次渲染时尝试填充所有内容,包括 LazyVerticalGrid?【参考方案3】:嵌套 RecyclerViews 的替代等效项是嵌套 LazyColumns,其中内部 LazyColumns 的 高度 是指定的或恒定的,而内部 LazyColumns 放置在 item 内 个块。
与公认的答案不同,这种方法依赖于 .height() 修饰符来避免“java.lang.IllegalStateException:在同一方向嵌套可滚动布局,如 ScrollableContainer 和 LazyColumn 是不允许的......”错误。此外,这种方法还解决了同方向嵌套滚动的情况。
这是一个示例代码和输出。
@Composable
fun NestedLists()
LazyColumn(Modifier.fillMaxSize().padding(12.dp),
horizontalAlignment = Alignment.CenterHorizontally)
//Header for first inner list
item
Text(text = "List of numbers:", style = MaterialTheme.typography.h5)
// First, scrollable, inner list
item
// Note the important height modifier.
LazyColumn(Modifier.height(100.dp))
val numbersList = (0 .. 400 step 4).toList()
itemsIndexed(numbersList) index, multipleOf4 ->
Text(text = "$multipleOf4", style = TextStyle(fontSize = 22.sp, color = Color.Blue))
// Header for second inner list
item
Text(text = "List of letters:", style = MaterialTheme.typography.h5)
// Second, scrollable, inner list
item
// Note the important height modifier.
LazyColumn(Modifier.height(200.dp))
val lettersList = ('a' .. 'z').toList()
itemsIndexed(lettersList) index, letter ->
Text(text = "$letter", style = TextStyle(color = Color.Blue, fontSize = 22.sp))
【讨论】:
你能解释一下接受的答案和你的答案有什么区别吗? 与接受的答案不同,我的答案依赖于 .height() 修饰符来避免“java.lang.IllegalStateException:不允许在相同方向的布局中嵌套可滚动,如 ScrollableContainer 和 LazyColumn... “ 错误。另外,我的回答解决了同方向嵌套滚动的情况。最后,在我的示例中,底部列表可以独立于顶部列表滚动。感谢您的澄清评论:)! 哦,好的。感谢您的澄清。我认为这与接受的答案相同。 @CherifDiallo:哇,这是有用的澄清。您能否将其编辑到您的答案中,以便未来的读者不会对差异感到困惑?谢谢。以上是关于Jetpack compose 中的 [NestedScrollView + RecyclerView] 或 [Nested RecyclerView (Recycler inside another的主要内容,如果未能解决你的问题,请参考以下文章