Dav*_*d A 3 android android-jetpack-compose android-jetpack-compose-layout android-compose-layout
I've been trying to build a list with a Card in it formatted like this:
The difficulty here is that the title e.g. "Bread" and ingredient name e.g. "Flour" can be very long and thus I want to have an ellipsis to keep things manageable i.e. "My Long Flour name" will be displayed as "My Long Flou..." or as much space as is allowed. The picture size and the gram and percent widths are constant .dp values.
Ellipsis worked fine when it was in a Column but with ConstraintLayout it doesn't seem to work and I get this:

here's my code
@Composable
fun BakeItem(
modifier: Modifier = Modifier,
bake: Bake,
cardClicked: () -> Unit,
ingredeints: List<Ingredient>
) {
Card(
modifier = modifier
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp)
.clickable { cardClicked() }
.fillMaxSize()
.wrapContentHeight(),
border = BorderStroke(4.dp, MaterialTheme.colorScheme.secondary),
shape = RoundedCornerShape(14.0.dp),
colors = cardColors(
containerColor = MaterialTheme.colorScheme.background
)
) {
val context = LocalContext.current
val uri = remember(bake.imagePath) { Uri.parse(bake.imagePath) }
// Card Content
ConstraintLayout(
modifier = modifier
.fillMaxSize()
.padding(start = 16.dp, top = 8.dp, end = 8.dp, bottom = 8.dp)
) {
val (titleRef, gramColRef, ingrColRef, percentColRef,
imageRef, dateRef, starsRef) = createRefs()
Text(
modifier = modifier
.padding(4.dp)
.constrainAs(titleRef) {
top.linkTo(parent.top, margin = 8.dp)
// end.linkTo(imageRef.start, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
}
.background(Color(0xffeeeeee)),
// textAlign = TextAlign.Left,
text = if (bake.recipeName.isEmpty()) "<Unnamed>" else bake.recipeName,
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary,
softWrap = false,
overflow = TextOverflow.Ellipsis,
)
Column(
horizontalAlignment = Alignment.End,
modifier = modifier
.width(50.dp)
.constrainAs(gramColRef) {
top.linkTo(titleRef.bottom, margin = 8.dp)
end.linkTo(ingrColRef.start, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
}
) {
ingredeints.forEachIndexed { _, it ->
Text(
text = it.weightGram,
style = MaterialTheme.typography.titleSmall,
softWrap = false,
overflow = TextOverflow.Ellipsis
)
}
}
Column(
modifier = modifier
.constrainAs(ingrColRef) {
top.linkTo(titleRef.bottom, margin = 8.dp)
start.linkTo(gramColRef.end, margin = 8.dp)
end.linkTo(ingrColRef.start, margin = 8.dp)
},
) {
ingredeints.forEachIndexed { _, it ->
Text(
text = it.name,
style = MaterialTheme.typography.titleSmall,
softWrap = false,
overflow = TextOverflow.Ellipsis
)
}
}
Column(
modifier = modifier
.width(50.dp)
.constrainAs(percentColRef) {
top.linkTo(titleRef.bottom, margin = 8.dp)
end.linkTo(imageRef.start, margin = 8.dp)
start.linkTo(ingrColRef.end, margin = 8.dp)
},
horizontalAlignment = Alignment.End
) {
ingredeints.forEachIndexed { i, it ->
Text(
text = if (i == 0) "" else it.bakingPercent,
style = MaterialTheme.typography.titleSmall,
softWrap = false,
overflow = TextOverflow.Ellipsis
)
}
}
Text(
modifier = modifier.padding(
top = 8.dp,
start = 4.dp,
end = 4.dp,
bottom = 4.dp
),
text = bake.notes,
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onSurface,
maxLines = 3
)
if (bake.imagePath.isNotEmpty()) {
Image(
modifier = modifier
.constrainAs(imageRef) {
top.linkTo(parent.top, margin = 8.dp)
end.linkTo(parent.end, margin = 8.dp)
}
.padding(4.dp)
.requiredSize(150.dp)
.clip(RoundedCornerShape(14.dp))
.border(
4.dp,
MaterialTheme.colorScheme.primaryContainer,
RoundedCornerShape(14.dp)
),
painter = rememberAsyncImagePainter(
remember(uri) {
ImageRequest.Builder(context)
.data(uri)
// TODO, think of caching improvements
// .diskCacheKey(uri.toString() + key.value)
// .memoryCacheKey(uri.toString() + key.value)
.diskCachePolicy(CachePolicy.DISABLED)
.memoryCachePolicy(CachePolicy.DISABLED)
.build()
}
),
contentScale = ContentScale.Crop,
contentDescription = "Image of your bake"
)
} else {
Spacer(modifier = modifier
.background(Color.Blue)
.width(150.dp)
.height(10.dp)
.constrainAs(imageRef) {
top.linkTo(parent.top, margin = 8.dp)
end.linkTo(parent.end, margin = 8.dp)
})
}
Text(
modifier = modifier
.padding(4.dp)
.constrainAs(dateRef) {
bottom.linkTo(parent.bottom, margin = 8.dp)
top.linkTo(imageRef.bottom, margin = 8.dp)
end.linkTo(parent.end, margin = 8.dp)
},
text = bake.startTime.toString(),
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface,
// textAlign = Layout.Alignment.ALIGN_CENTER
)
createHorizontalChain(
gramColRef, ingrColRef, percentColRef, imageRef,
chainStyle = ChainStyle.SpreadInside
)
createVerticalChain(
imageRef, dateRef,
chainStyle = ChainStyle.SpreadInside
)
createHorizontalChain(
titleRef, imageRef,
chainStyle = ChainStyle.SpreadInside
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
在标题中,您必须添加 constrain width = Dimension.fillToConstraints, end.linkTo(imageRef.start, margin = 8.dp)and maxLines = 1:
Text(
modifier = Modifier
.padding(4.dp)
.constrainAs(titleRef) {
top.linkTo(parent.top, margin = 8.dp)
end.linkTo(imageRef.start, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
width = Dimension.fillToConstraints
}
.background(Color(0xffeeeeee)),
text = "Recipe Name",
//...
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Run Code Online (Sandbox Code Playgroud)
对于列表而不是使用 3,Columns您可以做一些不同的事情。
对于成分名称添加weight(1f)修饰符和maxLines = 1
Column(
modifier = Modifier
.constrainAs(listRef) {
top.linkTo(titleRef.bottom, margin = 8.dp)
end.linkTo(imageRef.start, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
width = Dimension.fillToConstraints
}
) {
//forEach Row...
Row(Modifier.fillMaxWidth()) {
Text(text = "50g", Modifier.width(xx.dp), textAlign = TextAlign.End)
Text(
text = "Very long text long text",
Modifier
.padding(start=4.dp)
.weight(1f),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(text = "75%", Modifier.width(xx.dp), textAlign = TextAlign.End)
}
}
Run Code Online (Sandbox Code Playgroud)