Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

731
Vistas
Jetpack Compose Draw Arc with Dot Circle

I've looking to draw an arc on a canvas in Jetpack Compose with a little circle on the edge of progress like this picture:

enter image description here

I found how to draw the progress bar with arc canvas but don't know yet how to draw the circle to match with the edge of the arc line. This is my progress code:

@Composable
fun ComposeCircularProgressBar(
    modifier: Modifier = Modifier,
    percentage: Float,
    fillColor: Color,
    backgroundColor: Color,
    strokeWidth: Dp
) {
    Canvas(
        modifier = modifier
            .padding(strokeWidth / 2)
    ) {
        // Background Line
        drawArc(
            color = backgroundColor,
            135f,
            270f,
            false,
            style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Butt)
        )
        // Fill Line
        drawArc(
            color = fillColor,
            135f,
            270f * percentage,
            false,
            style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round)
        )
    }
}

Noted: for now I know to draw that circle is with Canvas.drawCircle(offset = Offset) but I don't know yet how to calculate the Offset(x,y) to match with the edge of progress.

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

This piece of code below will generate the arc with the circular dot based on the percentage you provide. You did get most of the part right, it was just about solving the Math Equation to find the point on the circle.

I assumed the radius of the circle as Height / 2 of the widget.

Since we are not drawing the full circle, the start angle is at 140 degrees and the maximum sweep angle is 260 degrees. (I found this by hit and trial, so that it looks as close to your image)

Now to draw the small white circle the center a.k.a offset has to be at (x,y) where x & y are given by the formula

x = radius * sin (angle in radians) y = radius * cos (angle in radians)

@Composable
fun ComposeCircularProgressBar(
    modifier: Modifier = Modifier,
    percentage: Float,
    fillColor: Color,
    backgroundColor: Color,
    strokeWidth: Dp
) {
    Canvas(
        modifier = modifier
            .size(150.dp)
            .padding(10.dp)
    ) {
        // Background Line
        drawArc(
            color = backgroundColor,
            140f,
            260f,
            false,
            style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round),
            size = Size(size.width, size.height)
        )

        drawArc(
            color = fillColor,
            140f,
             percentage * 260f,
            false,
            style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round),
            size = Size(size.width, size.height)
        )


        var angleInDegrees = (percentage * 260.0) + 50.0
        var radius = (size.height / 2)
        var x = -(radius * sin(Math.toRadians(angleInDegrees))).toFloat() + (size.width / 2)
        var y = (radius * cos(Math.toRadians(angleInDegrees))).toFloat() + (size.height / 2)

        drawCircle(
            color = Color.White,
            radius = 5f,
            center = Offset(x,  y)
        )
    }
}

Here are some examples I tried with

80% progress

@Preview
@Composable
fun PreviewPorgressBar() {
    ComposeCircularProgressBar(
        percentage = 0.80f,
        fillColor = Color(android.graphics.Color.parseColor("#4DB6AC")),
        backgroundColor = Color(android.graphics.Color.parseColor("#90A4AE")),
        strokeWidth = 10.dp
    )
}

45% progress

@Preview
@Composable
fun PreviewPorgressBar() {
    ComposeCircularProgressBar(
        percentage = 0.45f,
        fillColor = Color(android.graphics.Color.parseColor("#4DB6AC")),
        backgroundColor = Color(android.graphics.Color.parseColor("#90A4AE")),
        strokeWidth = 10.dp
    )
}

100% progress

@Preview
@Composable
fun PreviewPorgressBar() {
    ComposeCircularProgressBar(
        percentage = 1f,
        fillColor = Color(android.graphics.Color.parseColor("#4DB6AC")),
        backgroundColor = Color(android.graphics.Color.parseColor("#90A4AE")),
        strokeWidth = 10.dp
    )
}
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda