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 compose

我想在 Jetpack compose 中创建以下布局。

我试过在垂直滚动框内创建两个列表,但这是不可能的,因为我收到了这个错误: “java.lang.IllegalStateException:不允许在 ScrollableContainer 和 LazyColumn 等相同方向布局中嵌套可滚动。如果您想在项目列表前添加 header,请查看具有 DSL [的 LazyColumn 组件 api 允许首先通过 item() 函数添加 header,然后通过 items() 添加项目列表。

我尝试使用以下代码在 parent 列表中创建两个不同的列表,但这也不起作用。

@Composable
fun MainList() {
    LazyColumn() {
        
        item {
            /* LazyRow code here */
        }
        
        item {
            /* LazyColumn code here */
        }
    }
}

现在我不知道还有什么可以尝试在同一个 activity 上实现两个列表(一个垂直和一个水平)并保持 activity 垂直滚动。

您可以这样做:

   Column(Modifier.fillMaxWidth()) {

        LazyRow() {
            items(itemsList){
                  //.....
                }
        }

       LazyColumn() {
           items(itemsList2){
               //..
           }
       }
    }

或:

   Column(Modifier.fillMaxWidth()) {

        LazyRow() {
            items(itemsList){
               //....
            }
        }
       
       LazyVerticalGrid(cells = GridCells.Fixed(2)) {
           items(itemsList2.size){
               //....
           }
       }

    }

我认为最好的选择是 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 结果如下。

嵌套 RecyclerViews 的替代等效项是嵌套 LazyColumns,其中内部 LazyColumns 的 heights 是指定的或常量,并且内部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))
                }
            }
        }
    }
}