StavFX
07/13/2023, 6:22 PM.wrapContentWidth()
(red screenshot), it fills more than the width it needs after it wrapped the text to 2 lines.
I want it to shrink down to the size it actually needs. I can simulate this with a hardcoded .width(140.dp)
(blue screenshot).
How would I achieve this without hardcoding?Chris Sinco [G]
07/13/2023, 6:37 PMAnnotatedString
and change background in the SpanStyle
. Otherwise, setting background modifier on Text won’t work since it applies it to the whole container. @Halil Ozercan might know better thoughStavFX
07/13/2023, 6:38 PMStavFX
07/13/2023, 6:39 PMHalil Ozercan
07/13/2023, 6:59 PMwrapContentWidth
instructs Text composable to not care about incoming minimum width constraint. This doesn't do much in terms of wrapping the text horizontally. StaticLayout still wants to use all the width that's available. From what I see, wrap_second_line
wraps on its own because it cannot fit in the first line. As far as the overall size of the underyling StaticLayout goes, text still spans the whole width.
What you can do (after losing the initial frame), take the TextLayoutResult via onTextLayout
, find the width of every single line using lineCount
and getLineWidth
, after measuring the desired width and height for your background, use Modifier.drawBehind
to draw a rectangle as your background.Stylianos Gakis
07/13/2023, 7:01 PMStavFX
07/13/2023, 7:11 PMI might do something like this. There's no getLineWidth, but I guess, find the width of every single line usingonTextLayout
andlineCount
getLineWidth
getLineEnd() - getLineStart()
would accomplish that.
EDIT: Left/Right are probably what I want and not Start/EndStavFX
07/13/2023, 9:28 PMStavFX
07/13/2023, 9:29 PMHalil Ozercan
07/14/2023, 10:50 AMBoxWithConstraints
uses SubcomposeLayout which may introduce some performance drawbacks. Also, I would just suggest you to remember
the result of text measurement so it's not calculated in every recomposition.Tobias Suchalla
07/14/2023, 11:12 AM.wrapContentWidth()
.
I tried the following on desktop:
Box(
modifier = Modifier
.background(Color.Blue)
.padding(8.dp)
) {
Text(
text = "This is my text\nwith a second, longer line",
modifier = Modifier
.fillMaxWidth()
.background(Color.Gray)
.wrapContentWidth(Alignment.CenterHorizontally)
.background(Color.Red),
textAlign = TextAlign.Start
)
}
Which yields the attached image. No need for fancy manual text measuring.Stylianos Gakis
07/14/2023, 11:13 AM\n
in the text itself tough. The point was for the text to measure by itself without such hacks, and then have the result be laid out in the center.Tobias Suchalla
07/14/2023, 11:14 AMStylianos Gakis
07/14/2023, 11:15 AMHalil Ozercan
07/14/2023, 11:39 AMHalil Ozercan
07/14/2023, 11:41 AMwidth
, height
, size
, it's very likely that a Layout composable can do the same job.StavFX
07/14/2023, 6:38 PMStavFX
07/14/2023, 8:51 PMI would just suggest you toI can't usethe result of text measurement so it's not calculated in every recomposition.remember
remember
inside the MeasurePolicy block since it's not a @Composable, but I can't measure outside the Layout
, because I need the constraints. Is there a way to optimize this?
This is what I have so far (first time playing with Layout/measurables/placeables so feedback appreciated)Halil Ozercan
07/15/2023, 3:24 PMremember
advice was for the first solution. As you said, It wouldn't work when the measurement is done during the layout phase. In this case you can rely on TextMeasurer
's own internal cache. I think this solution is fine as it is.