3

I am attempting to create a vertical Likert scale using Jetpack Compose. Each field should include a vertical line that extends beyond its boundaries. I have also included an image to give an idea of what I am trying to achieve.

enter image description here

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
Jalson1982
  • 287
  • 4
  • 14

1 Answers1

3

You can use a Box to put a Canvas on top of the row items.

Something like:

Box(Modifier.fillMaxWidth()){

    //Just a simple for the row items
    Column(
        modifier = Modifier.fillMaxWidth(),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ){
        for (i in 1..5) {
            RoundedIem()
        }
    }

    //vertical Likert scale
    Canvas(modifier = Modifier.fillMaxWidth()){

        val height = 60.dp.toPx() //height of items
        val verticalOffset = 76.dp.toPx() //height + vertical padding

        val strokeWidthCircle =1f //stroke circle width
        val radiusCircle = 30f    //radius circle

        for (i in 0..4) {

            val circleCenterX = size.width-100f 
            val circleCenterY = height/2+ i*verticalOffset

            //Inner white circle
            drawCircle(
                color =  White,
                radius =  radiusCircle,
                center = Offset(circleCenterX ,circleCenterY),
            )

            //Stroke circle
            drawCircle(
                color =  DarkGray,
                radius =  radiusCircle,
                center = Offset(circleCenterX, circleCenterY),
                style = Stroke(width = strokeWidthCircle)
            )

            //vertical line
            if (i < 4) {

                val startY = circleCenterY + radiusCircle + strokeWidthCircle
                drawLine(
                    color = DarkGray,
                    start = Offset(
                        x = circleCenterX,
                        y = startY),
                    end = Offset(
                        x = circleCenterX,
                        y = startY + verticalOffset - strokeWidthCircle),
                    strokeWidth = strokeWidthCircle
                )
            }
        }
    }
}

@Composable
fun RoundedIem(){
    Row(
        modifier= Modifier
            .padding(horizontal = 16.dp)
            .fillMaxWidth()
            .height(60.dp)
            .clip(RoundedCornerShape(8.dp))
            .background(LightGray.copy(alpha = 0.5f))
            .padding(start = 10.dp),
        verticalAlignment = Alignment.CenterVertically,
    ){
        Text("Option")
    }
}

enter image description here

If you want to add also an icon in the circle you can draw the icon in the Canvas using:

//Icon
val painter = rememberVectorPainter(Icons.Default.Done)

Canvas(modifier = Modifier.fillMaxWidth()){

        //previous code
   

        val iconSize = 60f
        //circle center - iconSize/2
        translate(
            left = circleCenterX - iconSize/2,
            top = circleCenterY - iconSize/2
        ) {
            with(painter) {
                draw(
                    size = Size(iconSize,iconSize),//painter.intrinsicSize,
                    colorFilter = ColorFilter.tint(Color.Blue)
                )
            }
        }
}

enter image description here

With a background:

            drawCircle(
                color =  Blue,
                radius =  radiusCircle-8f,
                center = Offset(circleCenterX,circleCenterY),
            )

            //circle center - iconSize/2
            val iconSize = 48f
            translate(
                left = circleCenterX- iconSize/2,
                top = circleCenterY -iconSize/2
            ) {
                with(painter) {

                    draw(
                        size = Size(iconSize,iconSize),//painter.intrinsicSize,
                        colorFilter = ColorFilter.tint(Color.White)
                    )
                }
            }

enter image description here

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • Hey it looks nice. Can you maybe tell me is it possible to add background and icon inside circle to have selected state? – Jalson1982 Jan 29 '23 at 14:02
  • @Jalson1982 I've updated the answer with the example of an icon. For the background you can simply change the `color = White` in the inner circle. – Gabriele Mariotti Jan 29 '23 at 15:54