Jetpack Compose,我有多张卡在垂直滚动列中有内部脚手架,如果你不给卡特定高度它崩溃

Jetpack Compose,I have multiple cards have scaffold inside, in a vertical scrollable column and if you don't give the card specific height it crashes

在我们的应用程序中,有很多自定义视图都是带有 3 个插槽的卡片 header、内容和底部,所以我认为我们可以在卡片内部使用脚手架来处理它,除了有很多 if/else 条件

所以我创建了这个基本可组合函数 ->

@Composable
fun DynamicTile(
    modifier: Modifier = Modifier,
    headContent: @Composable () -> Unit,
    mainContent: @Composable (PaddingValues) -> Unit = { },
    bottomContent: @Composable () -> Unit = { }
) {
    Card( modifier = modifier) {
        Scaffold(
            topBar = headContent,
            content = mainContent,
            bottomBar = bottomContent
        )
    }
}

然后不同的实现不同的目的,我这里说两个目的 例如显示特定图像、动画、地图和... ->

对于这个,您应该将本地可绘制对象添加到图像以进行编译

@Composable
fun TileTeaser( modifier: Modifier = Modifier) {
    with(entity) {
        DynamicTile(
//            modifier = modifier.then(Modifier.height(250.dp)),
            headContent = {
                Text(
                    text = "headline",
                   
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(start = 16.dp, end = 16.dp, top = 8.dp)
                )
            },
            mainContent = {
                 val painter = rememberImagePainter(
                    data = painterResource(R.drawable.ds_ic_add))
                Image(
                    contentScale = ContentScale.Crop,
                    painter = painter,
                    modifier = modifier,
                    contentDescription = null
                )
            },
            bottomContent = {
                     Box(modifier = Modifier.fillMaxWidth()) {
                    Button(
                        onClick = { }, modifier = Modifier
                            .align(Alignment.Center)
                            .wrapContentSize()
                    ) {
                        Text(text = "Button")
                    }
                }
                }
            }
        )
    }
}

而这个是用Lottie制作的动画,你应该添加local raw来编译它

@Composable
fun TileAnimation(modifier: Modifier = Modifier) {
    DynamicTile(
        modifier = modifier.then(Modifier.height(300.dp)),
        headContent = {
            Text(
                text = "headline",
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(start = 16.dp, end = 16.dp, top = 8.dp)
            )
        },
        mainContent = {
            val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.sth))
            Card(
                modifier = Modifier
                    .height(183.dp)
                    .then(modifier),
                shape = RoundedCornerShape(0.dp)
            ) {
                LottieAnimation(
                    composition = composition,
                    modifier = modifier
                        .fillMaxSize(),
                    contentScale = ContentScale.Crop,
                )
            }
        },
        bottomContent = {
            Box(modifier = Modifier.fillMaxWidth()) {
                Button(
                    onClick = { }, modifier = Modifier
                        .align(Alignment.Center)
                        .wrapContentSize()
                ) {
                    Text(text = "Button")
                }
            }
        }
    )
}

然后我像这样将它们加载到列中

@Composable
fun LoadScreen() {
    Column(
        modifier = Modifier
            .padding(16.dp)
            .verticalScroll(rememberScrollState())
    ) {
        Text(text = "Teaser")

        TileTeaser(
            modifier = Modifier.padding(top = 16.dp)
        )
        
        Text(
            text = "Animation",
            modifier = Modifier.padding(top = 16.dp)
        )

        TileAnimation(modifier = Modifier.padding(vertical = 16.dp))
    }
}

如你所见,如果我评论卡片的Modifier.height, 它因此错误而崩溃 ->

  java.lang.IllegalArgumentException: Can't represent a size of 2147483563 in Constraints
        at androidx.compose.ui.unit.Constraints$Companion.bitsNeedForSize(Constraints.kt:408)
        at androidx.compose.ui.unit.Constraints$Companion.createConstraints-Zbe2FdA$ui_unit_release(Constraints.kt:368)

Kotlin 版本 1.6.10 和 compose 1.1.0,这是 lottie 库 ->

implementation "com.airbnb.android:lottie-compose:4.2.2"

顺便说一句,您可以从 here

下载 Lottie 文件

提前感谢您的帮助

TL;DR 不要将 Scaffold 放在可滚动内容的 Card 中。 :)

如果我们深入研究 Scaffold 代码,我们会发现它实际上正在创建一个 ScaffoldLayout,这将创建一个使用约束的 SubcomposeLayout,更具体地说是以下宽度和身高:

val layoutWidth = constraints.maxWidth
val layoutHeight = constraints.maxHeight

现在,如果没有为上面的 layoutWidthlayoutHeight 设置预定义值,它们将等于 Int.MAX_VALUE,即 2147483647,这就是您在 [=19] 中看到的=](给予或索取)。

当您以正确的方式使用脚手架时,通常作为 UI 的根,Android 为您施展魔法并计算出正确的大小。

我的建议是,用另一种类型的布局替换脚手架,或者如果自定义布局不够用:

https://developer.android.com/jetpack/compose/layouts/custom