Reputation: 1653
My layout consists of 2 texts with an arrow image between them. All elements are placed in a composable Row and aligned to the left, right behind eachother. When the texts are short it looks like this:
|Origin → destination |
When the texts are too long, I'd like them to ellipsise with max 1 line. If the 'destination' is too long, it works as expected:
|Origin → looooooooongDest...|
But what if the 'origin' text is too long?
|LooooooooooooooongOrigin → .|
<<< wrong!
In xml ConstraintLayout I'd use a layout_constraintWidth_percent=0.5 for the first text, which results in the following:
|Loooooooo... → destination |
Simply put, this is my request:
How can I achieve this in compose?
Note: I've tried using combinations of .weight(0.5F)
and .weight(0.5F, fill = false)
on either the first or both texts. These are some of the results I got with these solutions, which is not what want either, but I think I'm getting closer to the desired result with these modifiers:
|Origin → destination |
<<< wrong!
|Or.. → looooooongDestination|
<<< wrong!
My latest code is getting close to the desired solution:
Row {
Text(
modifier = Modifier.weight(0.5F, fill = false),
text = "Origin",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Icon(
modifier = Modifier.padding(horizontal = 4.dp),
...
)
Text(
modifier = Modifier.weight(0.5F),
text = "Destination",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
Although this seems to work as expected for the 1st text, it always truncates the 2nd text to 50% width:
|Origin → loooongDest... |
<<< wrong!
Upvotes: 1
Views: 871
Reputation: 812
You can similarly use fillMaxWidth(faction:Float)
along with constraintAs {...}
on a child in ConstraintLayout in Compose as below where faction:Float
ranges from 0f to 1f:
modifier = Modifier
.fillMaxWidth(.5f) // fraction = .5f for half width of screen
.constrainAs(soochak) {
start.linkTo(parent.start)
...
}
Upvotes: 0
Reputation: 5323
If you know ConstraintLayout you can implement directly in ConstraintLayout for compose. Here is approximately what you described in ConstraintLayout Compose: It will clip the first text when it grows past 50% It will use the rest and clip if it fills the rest of the ConstraintLayout container.
It has 2 syntaxes. JSON is a little easier to read the constraints as it is separated. The DSL is a little more compact and more in the style of the rest of Compose.
Here are the examples in both formats:
@OptIn(ExperimentalMotionApi::class)
@Preview
@Composable
fun DemoCLText() {
val c = ConstraintSet("""{
midpoint: { type: 'vGuideline', percent: 0.50 },
origin: {
width: { value: 'preferWrap', max: 'wrap' },
start: ['parent', 'start', 0],
end: ['midpoint', 'start', 0],
centerVertically: 'parent',
hBias:0
},
arrow: {
width: 'wrap',
centerVertically: 'parent',
start: ['origin', 'end', 0],
},
destination: {
width: { value: 'preferWrap', max: 'wrap' },
start: ['arrow', 'end', 0],
end: ['parent', 'end', 2],
hBias: 0,
centerVertically: 'parent'
},
}
"""
);
ConstraintLayout(
constraintSet = c,
modifier = Modifier.width(200.dp).background(Color.LightGray)
) {
Text(
modifier = Modifier.layoutId("origin"),
text = "Origin",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Text(
modifier = Modifier.layoutId("arrow"),
text = "→",
)
Text(
modifier = Modifier.layoutId("destination"),
text = "Destination",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
@OptIn(ExperimentalMotionApi::class)
@Preview
@Composable
fun DemoCLText2() {
ConstraintLayout(
modifier = Modifier.width(140.dp).background(Color.LightGray)
) {
val origin = createRef()
val midpoint = createGuidelineFromAbsoluteRight(0.5f)
Text(
modifier = Modifier.constrainAs(origin) {
centerVerticallyTo(parent)
start.linkTo(parent.start)
end.linkTo(midpoint)
width = Dimension.preferredWrapContent.atMostWrapContent
horizontalBias = 0f
},
text = "Origin",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
var arrow = createRef();
Text(
modifier = Modifier.constrainAs(arrow) {
centerVerticallyTo(parent)
start.linkTo(origin.end)
width = Dimension.wrapContent
},
text = "→",
)
Text(
modifier = Modifier.constrainAs(createRef()) {
centerVerticallyTo(parent)
start.linkTo(arrow.end)
end.linkTo(parent.end)
width = Dimension.preferredWrapContent.atMostWrapContent
horizontalBias = 0f
},
text = "Destination",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
Upvotes: 0