我正在 Jetpack Compose 中构建一个简单的应用程序。在应用程序的“主页”部分中,我显示了一个项目列表。没什么好看的。 我使用
LazyColumn
内的自定义卡来完成此操作。
应用程序加载时,将显示列表,然后首次显示项目。然后我向下滚动,所有项目都按预期显示在
custom card
中。 image
会完全忽略它的 contentScale
和它的 modifier
并破坏布局。非常奇怪的事情。 custom card
和 columns
构建 rows
。 ConstraintLayout
构建了它。 remember
modidier
。 custom card
,其中具有定义的 height
(180.dp) 和 fillMaxWidth
。image
放置在start
的custom card
上,其高度和宽度应固定(例如宽度:124.dp,高度:180.dp)。@Composable
fun ProductCard(
data: ProductDisplayData,
onClick: (ProductDisplayData) -> Unit = {}
) {
val constraints = ConstraintSet {
val imageSection = createRefFor("imageSection")
val textSection = createRefFor("textSection")
constrain(imageSection) {
top.linkTo(parent.top)
start.linkTo(parent.start)
end.linkTo(textSection.start)
width = Dimension.value(128.dp)
height = Dimension.value(180.dp)
}
constrain(textSection) {
top.linkTo(parent.top)
start.linkTo(imageSection.end)
bottom.linkTo(parent.bottom)
end.linkTo(parent.end)
width = Dimension.fillToConstraints
height = Dimension.fillToConstraints
}
}
ConstraintLayout(constraints, modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(8.dp))
.padding(vertical = 8.dp)
.clickable { onClick(data) }
) {
if (data.image != null) {
Box(
modifier = Modifier
.layoutId("imageSection")
.height(180.dp)
.width(128.dp)
.clip(RoundedCornerShape(8.dp))
.clipToBounds()
) {
Image(
bitmap = data.image.asImageBitmap(),
contentDescription = "Product Image",
modifier = Modifier
.fillMaxSize()
)
}
}
Column(
modifier = Modifier
.layoutId("textSection")
.fillMaxWidth()
.padding(8.dp),
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = data.name,
fontWeight = FontWeight.Bold,
fontSize = 18.sp,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.weight(1f)
)
Text(text = "${data.price}$" )
}
Text(text = data.brand, fontWeight = FontWeight.Bold, fontSize = 14.sp)
Text(text = data.size, modifier = Modifier, fontWeight = FontWeight.SemiBold, fontSize = 12.sp, fontStyle = FontStyle.Italic)
Text(text = data.category, fontWeight = FontWeight.SemiBold, fontSize = 12.sp)
LazyRow {
items(data.tags) { tag ->
Chip(
name = tag,
isSelected = false,
onSelectionChanged = {}
)
}
}
Text(
text = data.description,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
fontWeight = FontWeight.Light,
fontSize = 12.sp
)
}
}
}
image
的唯一特点是它作为 base64
字符串出现在响应中,并从中转换为 bitmap
。这就是为什么我使用 Image
而不是 coil (AsyncImage)
来显示图像。
由于长度原因,我无法为此 MRE 放置 base64 字符串。 ProductCard
代码已发布在上面。
data class ProductDisplayData(
val id: Int,
val name: String,
val description: String,
val size: String,
val ownerName: String,
val ownerID: Int,
val price: String,
val category: String,
val brand: String,
val tags: List<String>,
val image: Bitmap?
)
val products = listOf(
ProductDisplayData(
id = 0,
name = "Polo",
description = "Nice slim fit polo shirt, perfect for casual wear, available in multiple colors",
size = "Small",
price = "120",
image = bitmapFromBase64String,
brand = "Boss",
category = "Shirts",
tags = listOf("Shirts", "Boss", "Slim fit", "Casual", "Polo", "Small"),
ownerName = "John Doe",
ownerID = 0
)
//repeat it until the list overflows...
)
@Composable
fun HomeScreen() {
LazyColumn(
modifier = Modifier.fillMaxWidth(),
contentPadding = PaddingValues(vertical = 16.dp),
) {
items(products) { product ->
ProductCard(
data = product
) { productSelected ->
// do action... irrelevant for this issue.
}
}
}
}
非常有趣的细节是,如果我使用
coil (AsyncImage)
应用硬编码的 url 进行测试,则不会发生此问题并且它可以正常工作。我是不是遇到了 androidx.compose.foundation.Image
Bug?
我花了两天时间才解决这个极其奇怪的问题。我使用
Coil
函数 rememberAsyncImagePainter
修复了它。我不能 100% 确定这是否是更合适的方法,但它应该有效。 这就是
Image
代码的样子:
Image(
contentScale = ContentScale.Crop,
painter = rememberAsyncImagePainter(it),
contentDescription = "Product Image",
modifier = Modifier
.clipToBounds()
.height(180.dp)
.width(128.dp)
.layoutId("imageSection")
.clip(RoundedCornerShape(8.dp))
)