I am using the Jetpack glance framework for creating widgets in Android, and I have encountered a problem when using text inside a row.
Expected behavior:- Text should truncate as soon as it touches the other element inside the row
Actual behavior:- Text first pushes the other elements out of the view and then truncates
Here is the screenshot of the issue
This is fine
This is not
Box(modifier = GlanceModifier.background(ColorProvider(day = backgroundColor, night = backgroundColorDark))
.padding(
horizontal = 14.dp,
vertical = 14.dp).clickable(onClick = actionStartActivity<MainActivity>(context, Uri.parse(widgetUri)))) {
Column(
modifier = GlanceModifier.fillMaxSize(),
verticalAlignment = Alignment.Vertical.Top,
horizontalAlignment = Alignment.Horizontal.Start,
) {
Row(
modifier = GlanceModifier.fillMaxWidth(),
horizontalAlignment = Alignment.Horizontal.CenterHorizontally,
verticalAlignment = Alignment.Vertical.CenterVertically
) {
Row(
verticalAlignment = Alignment.Vertical.CenterVertically)
{
Box (
modifier = GlanceModifier.clickable(onClick = actionRunCallback<ToggleAction>(
parameters = actionParametersOf(habitIdKey to habitId)
))
) {
Image(
provider = ImageProvider(R.drawable.check_24), contentDescription = null,
colorFilter = ColorFilter.tint(
if (isTodayCompleted)
ColorProvider(day = Color.White, night = Color.White)
else
ColorProvider(day = getColor(backgroundColor), night = getColor(backgroundColor))
),
modifier = GlanceModifier
.size(30.dp)
.then(
if (isTodayCompleted) {
GlanceModifier.background(
imageProvider = ImageProvider(R.drawable.fab_shape),
colorFilter = ColorFilter.tint(ColorProvider(day = getColor(backgroundColor), night = getColor(backgroundColor)))
) // Apply background when today is completed
} else {
GlanceModifier.background(
imageProvider = ImageProvider(R.drawable.fab_outline),
colorFilter = ColorFilter.tint(ColorProvider(day = getColor(backgroundColor), night = getColor(backgroundColor)))
) // Apply border when today is not completed
}
)
)
}
Column(modifier = GlanceModifier.padding(horizontal = 10.dp))
{
Text("${DateFormat.format("MMMM",today)}",
maxLines = 1,
style = TextStyle(
color = ColorProvider(day = Color.Gray, night = Color.Gray),
fontWeight = FontWeight.Normal,
textAlign = TextAlign.Start,
fontSize = 12.sp))
Text("$title",
maxLines = 1,
style = TextStyle(
color = ColorProvider(day = textColor, night = textColorDark),
fontWeight = FontWeight.Medium,
textAlign = TextAlign.Start,
fontSize = 16.sp))
}
}
Spacer(GlanceModifier.defaultWeight())
Column(
verticalAlignment = Alignment.Vertical.CenterVertically,
horizontalAlignment = Alignment.Horizontal.CenterHorizontally,
) {
Row(
horizontalAlignment = Alignment.Horizontal.CenterHorizontally,
verticalAlignment = Alignment.Vertical.CenterVertically
) {
Text("$currentStreak",
style = TextStyle(
color = ColorProvider(day = textColor, night = textColorDark),
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Start,
fontSize = 14.sp))
Image(
provider = ImageProvider(if (isTodayCompleted)
R.drawable.fire_filled
else R.drawable.fire_outline
), contentDescription = null,
colorFilter = ColorFilter.tint(ColorProvider(day = getColor(backgroundColor), night = getColor(backgroundColor))),
modifier = GlanceModifier.size(14.dp)
)
}
Text(
if (currentStreak.toInt() == 1) "DAY" else
"DAYS",
modifier = GlanceModifier.padding(horizontal = 2.dp),
style = TextStyle(
color = ColorProvider(day = textColor, night = textColorDark),
fontWeight = FontWeight.Normal,
textAlign = TextAlign.Start,
fontSize = 10.sp))
}
}
}
Your middle column (or shall we call it group, as you don't have an explicit column for the first/leftmost vertical group) needs to be able to grow and acquire as much space as it can without stepping on the third (rightmost) column.
To do so, you need to let the rightmost column take up the space it needs based on its content (WrapContentWidth), and allow the middle column to be flexible in its width by setting its weight (available in row scope) to 1f (which, in Glance, is defaultWeight()). Note that
The parent will divide the horizontal space remaining after measuring unweighted child elements
which means the unweighted siblings (including column 3) are measured first, thus assuring they are allocated the needed space.
interface RowScope {
/**
* Size the element's width to split the available space with other weighted sibling elements
* in the [Row]. The parent will divide the horizontal space remaining after measuring
* unweighted child elements and distribute it according to the weights, the default weight
* being 1.
*/
fun GlanceModifier.defaultWeight(): GlanceModifier
}
Below is a simplified version. Previews with different width and how the text grows/truncates.
@Composable
@OptIn(ExperimentalGlancePreviewApi::class)
@Preview(widthDp = 340, heightDp = 100)
@Preview(widthDp = 230, heightDp = 100)
@Preview(widthDp = 130, heightDp = 100)
fun Test(){
Box(modifier = GlanceModifier.padding(14.dp)) {
Row(
modifier = GlanceModifier.fillMaxWidth(),
horizontalAlignment = Alignment.Horizontal.CenterHorizontally,
verticalAlignment = Alignment.Vertical.CenterVertically
) {
Image(
provider = ImageProvider(R.drawable.sun_68),
contentDescription = null,
modifier = GlanceModifier.size(30.dp),
contentScale = ContentScale.Crop)
Column (
modifier = GlanceModifier.padding(1.dp).defaultWeight(),
horizontalAlignment = Alignment.Horizontal.Start,
verticalAlignment = Alignment.Vertical.CenterVertically
)
{
Text(
text = "This text can be truncated or it can fit ",
modifier = GlanceModifier.padding(horizontal = 8.dp),
style = TextStyle(
color = ColorProvider(day = Color.White, night = Color.White),
fontSize = 14.sp
),
maxLines = 1)
Text(
text = "But it will not push out rightmost column",
modifier = GlanceModifier.padding(horizontal = 8.dp),
style = TextStyle(
color = ColorProvider(day = Color.White, night = Color.White),
fontSize = 10.sp
),
maxLines = 1)
}
Column (
modifier = GlanceModifier.wrapContentWidth(),
horizontalAlignment = Alignment.Horizontal.Start,
verticalAlignment = Alignment.Vertical.CenterVertically
){
Text(
"Right",
maxLines = 1)
Text(
"side",
maxLines = 1)
}
}
}
}