Nathan Castlehow

    Nathan Castlehow

    1 year ago
    Hi All, Wondering if anyone has thoughts on the best way to reserve space based on textSize (width wise)? Current use case is I have an area I which could have 0 to N characters in it (in reality itll be just 1,2, or 3 characters). I want the space to always be wide enough for the N characters based on the users current fontscale settings? My understanding is that it really depends on the font as to how much width each character will take?
    I guess if its even possible itll only be possible on monospaced fonts. Such a rabbit hole 🤦. It’ll be 3 numbers that may eventually occupy the space so could work from there I guess?
    Colton Idle

    Colton Idle

    1 year ago
    Hacky I suppose but Box{ Text("MMM", color = Color.Transparent) Text(actualText) } The box will always measure to be at least those 3 chars long, but be transparent. Leaving your real text on top.
    Nathan Castlehow

    Nathan Castlehow

    1 year ago
    Yeah, I normally go with a variation of that. Not great for accessibility though I guess but it gets the job done.
    Colton Idle

    Colton Idle

    1 year ago
    Yeah, someone else could definitely chime in, but I'm not sure how else you get around measuring something to be 3 chars long if you don't have 3 chars. I suppose you could abstract all of it in a layout, but I've added my 2 cents. Someone else with a better idea could probably chime in. Good luck!
    Halil Ozercan

    Halil Ozercan

    1 year ago
    Recently there was a discussion on how to understand if text is longer than 2 lines before layout phase is completed. You can always use
    TextLayoutResult
    but it makes you lose a frame. I wanted to check whether it's possible with
    SubcomposeLayout
    . I'm not able to test it out right now but the idea is basically;
    SubcomposeLayout { constraints ->
      val measurable = subcompose("3chars") {
        Text("WWW", ...)
      }
      // get the supposed width from this subcomposition but don't place it in the final layout
      val actualPlaceable = subcompose("") {
        Text("..,", )
      }.single().measure(constraints.constrain(...))
      layout(a, b) {
        actualPlaceable.placeRelative...
      }
    }
    Nathan Castlehow

    Nathan Castlehow

    1 year ago
    @Halil Ozercan were you thinking something like this? (Not super familiar with custom layouts in compose) This works fairly well (currently setup to right align text). It reserves too much space for me but I assume its because its not using a monospaced font.
    @Composable
    fun TextWithReservedSpace(
        text: String,
        modifier: Modifier = Modifier,
        color: Color = Color.Unspecified,
        style: TextStyle = LocalTextStyle.current,
        reservedCharLength: Int,
    ) {
        val reservedWidthString = remember(reservedCharLength) {
            "W".repeat(reservedCharLength)
        }
    
    
        SubcomposeLayout { constraints ->
    
            // get the supposed width from this subcomposition but don't place it in the final layout
            val measurable = subcompose("reserved_space") {
                Text(
                    reservedWidthString,
                    style = style,
                    modifier = modifier,
                )
            }.single().measure(constraints)
    
            val actualPlaceable = subcompose("") {
                Text(
                    text,
                    color = color,
                    style = style,
                    modifier = modifier
                )
            }.single().measure(constraints)
    
    
            layout(measurable.width, measurable.height) {
                actualPlaceable.placeRelative(measurable.width - actualPlaceable.width, 0)
            }
        }
    }
    Halil Ozercan

    Halil Ozercan

    1 year ago
    @Nathan Castlehow exactly! W is most of the time the widest character in a font, it's normal that it takes too much space.
    Nathan Castlehow

    Nathan Castlehow

    1 year ago
    Thanks for your help! 🙂