Jetpack Compose:如何在卡片内包装列表项

3
我有一个屏幕,需要显示一个标题和一个包含项目的卡片视图。整个屏幕都需要可滚动(如下图所示)。

enter image description here

我知道如何使用可滚动的Column来实现这个,但我想要使用LazyColumn(因为每个列表项都有自己的ViewModel,由于视图的复杂性,我认为LazyColumn会更加节约资源)。对于标题,我可以使用item,对于列表,我可以使用items。以下是我尝试的代码:
@Composable
fun Screen(
  items: List<String>
) {
  Column(
    Modifier.fillMaxSize()
  ) {
    TopAppBar(title = { Text(text = "My Activity") })

    LazyColumn {

      // Header
      item {
        Text("Title", Modifier.padding(32.dp))
      }

      // I cannot use Box in this way here
      Box(Modifier.padding(32.dp)) {
        Card {
          items(items.size) {
            Text("Item $it")
          }
        }
      }
    }
  }
}

那段代码的问题在于我无法将列表项包装在卡片视图中,因为Card不是LazyListScope。使用LazyColumn,我该如何将列表项包装在卡片中?

之前已经有人问过同样的问题,但目前还没有答案:( - Abhimanyu
这是一个基本的用例。我很惊讶这是不可能的。 - Diego Palomar
你是怎么制作那个gif的?使用Xml View吗? - Om Kumar
@OmKumar,你可以拍摄一个视频,然后将视频转换为gif文件。 - Sepideh Vatankhah
有关此事有任何更新吗?我也处于同样的情况。 - cwiesner
2个回答

0
作为一种解决方法,您可以通过绘制自定义形状来模拟卡片。
它会看起来像这样:screen_record
sealed class Item
class HeaderItem(...): Item()
class ContentItem(...) : Item()

...

val items: SnapshotStateList<Item> = mutableStateListOf()

...

LazyColumn(
        modifier = Modifier.fillMaxSize(),
    ) {
        itemsIndexed(
            items = state.items,
        ) { index, item ->

            val prevItem = state.items.getOrNull(index - 1)
            val nextItem = state.items.getOrNull(index + 1)

            Column {
                when (item) {
                    is HeaderItem -> Header(item)

                    is ContentItem -> {
                        Box(
                            modifier = Modifier
                                .heightIn(min = 48.dp)
                                .fillMaxWidth()
                                .clip(shape = getShape(prevItem, nextItem, 16.dp))
                                .background(Color.Green.copy(0.3F))
                        ) {
                            Item(item)
                        }
                    }
                }
            }
        }

fun getShape(prevItem: Item?, nextItem: Item?, corner: Dp): Shape {
    return if (prevItem is ContentItem && nextItem is ContentItem) {
        //FLAT
        RectangleShape
    } else if (prevItem !is ContentItem && nextItem !is ContentItem) {
        //ROUNDED_ALL
        RoundedCornerShape(corner)
    } else if (prevItem !is ContentItem) {
        //ROUNDED_TOP
        RoundedCornerShape(topStart = corner, topEnd = corner)
    } else {
        //ROUNDED_BOTTOM
        RoundedCornerShape(bottomStart = corner, bottomEnd = corner)
    }
}

-1
你有点混淆了,应该将Card放在items调用内部:
    LazyColumn {
      // Header
      item {
        Text("Title", Modifier.padding(32.dp))
      }
      
      items(items.size) {
          // You can use Box in this way here
          Box(Modifier.padding(32.dp)) {
            Card {
              Text("Item $it")
            }
          }
       }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接