I am working on a Composable that is essentially t...
# compose
j
I am working on a Composable that is essentially this: https://s3.amazonaws.com/cdn.freshdesk.com/data/helpdesk/attachments/production/35122[…]3/original/pHTRjVez4mINgemCp15Ws5OFNs3a-xBXjw.jpg?1620046726. Anyone have thoughts on the best way to achieve something similar? See my thoughts in 🧵
So the main challenge is the labels on the bottom. This UI has to be dynamic to allow scales of different ranges and sizes so I am dynamically adding each number to it based on the definition I get back from the server. The labels will need to go in a separate row from what I can tell since they are aligned with one item, but can spread out into the space of other items horizontally.
I’m thinking this is a good use case for a ConstraintLayout. I know I could achieve it with a custom layout, but I’m trying to see if I can make it a little more simple than a custom layout.
z
I think “simple” is maybe subjective here 😜 Could be something as simple as this for the lines and labels themselves:
Copy code
@Composable
fun NumberLine(
    count: Int,
    numberLabel: @Composable (Int) -> Unit
) {
    require(count > 0)

    Row(horizontalArrangement = Arrangement.SpaceBetween) {
        for (i in 0 until count) {
            Column(horizontalAlignment = Alignment.CenterHorizontally) {
                Box(
                    Modifier
                        .size(1.dp, 50.dp)
                        .background(Color.Black)
                )
                numberLabel(i)
            }
        }
    }
}
It’s not much more to add the gradient, but depends how you want your component to interact with incoming height constraints.
So you might want to, for example, measure all the labels first, then calculate how much space is available to make all the lines the same height, and then draw the lines and the gradient in a single draw modifier.
j
Ah yeah, sorry for not being clear enough. The gradient is not actually in our UI. I just grabbed a similar thing offline. The main complexity I’m running into is laying out the marks and the labels in a dynamic manner
This is much more similar to what I’m doing:

https://prod.smassets.net/assets/cms/sm/uploads//nps-question-survey-question-types-1130x313.png

except the “Not At All likely” type labels are on the bottom and they are under a “tick” mark linking them visually to the number they are associated with.
It’s that “tick” mark and the labels that I’m trying to lay out. The marks and labels can be set to arbitrary numbers on the scale and there can be more than 2 of them
I have it working. I ended up going with two rows. One row lays out the number scale which is easy to do dynamically with basic Composables and modifiers. The second row goes through each number again to see if a mark needs to be drawn and then I draw a column with the mark and the label under it. I ended up solving the label layout by using the
wrapContentWidth(unbound=false)
modifier.
This allows the label to exceed the bounds of a single block, while still anchoring it to the block that it is describing
I could do it with one row, but then I have to do a lot of custom drawing to do the border for the scale so two rows seemed best for my case
there’s still some complexity to ensure that labels don’t overlap, but I was able to work that out
shoutout to @Filip Wiesner for the wrapContentWidth suggestion which was clutch.
❤️ 1