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
现在,如果没有为上面的 layoutWidth
和 layoutHeight
设置预定义值,它们将等于 Int.MAX_VALUE
,即 2147483647,这就是您在 [=19] 中看到的=](给予或索取)。
当您以正确的方式使用脚手架时,通常作为 UI 的根,Android 为您施展魔法并计算出正确的大小。
我的建议是,用另一种类型的布局替换脚手架,或者如果自定义布局不够用:
https://developer.android.com/jetpack/compose/layouts/custom
在我们的应用程序中,有很多自定义视图都是带有 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
现在,如果没有为上面的 layoutWidth
和 layoutHeight
设置预定义值,它们将等于 Int.MAX_VALUE
,即 2147483647,这就是您在 [=19] 中看到的=](给予或索取)。
当您以正确的方式使用脚手架时,通常作为 UI 的根,Android 为您施展魔法并计算出正确的大小。
我的建议是,用另一种类型的布局替换脚手架,或者如果自定义布局不够用:
https://developer.android.com/jetpack/compose/layouts/custom