Rectangle border progress bar
A

1

6

How i Draw Rectangle progress bar as a below in photo as CircleProgress indicator in android with JetpackCompose https://drive.google.com/file/d/1SXZcBp7uAesl-i6gHqFNXNpnc54Z6vdI/view?usp=share_link

CircularProgressIndicator(strokeWidth=10.dp,
                          progress = 1.0f,
                            color = Red,
                           modifier = Modifier.height(200.dp).width(200.dp).align(Alignment.Center))
Ancell answered 15/3, 2023 at 14:12 Comment(0)
E
9

You can change how to get progress for path progress i post an answer with 3 different alternatives

Result

enter image description here

First create a path and add Rounded rectangle

 if (path.isEmpty) {
                    path.addRoundRect(
                        RoundRect(
                            Rect(offset = Offset.Zero, size),
                            cornerRadius = CornerRadius(100.dp.toPx(), 100.dp.toPx())
                        )
                    )
                }

Then measure path using

    val pathMeasure by remember { mutableStateOf(PathMeasure()) }

            pathWithProgress.reset()

            pathMeasure.setPath(path, forceClosed = false)
            pathMeasure.getSegment(
                startDistance = 0f,
                stopDistance = pathMeasure.length * progress / 100f,
                pathWithProgress,
                startWithMoveTo = true
            )

Then draw this path and original Path as in implementation

@Preview
@Composable
private fun BorderProgressBar() {

    val startDurationInSeconds = 10
    var currentTime by remember {
        mutableStateOf(startDurationInSeconds)
    }

    var targetValue by remember {
        mutableStateOf(100f)
    }

    var timerStarted by remember {
        mutableStateOf(false)
    }
    LaunchedEffect(key1 = timerStarted) {
        if (timerStarted) {
            while (currentTime > 0) {
                delay(1000)
                currentTime--
            }
        }
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(40.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        // This is the progress path which wis changed using path measure
        val pathWithProgress by remember {
            mutableStateOf(Path())
        }

        // using path
        val pathMeasure by remember { mutableStateOf(PathMeasure()) }

        val path = remember {
            Path()
        }

        val progress by animateFloatAsState(
            targetValue = targetValue,
            animationSpec = tween(startDurationInSeconds * 1000, easing = LinearEasing)
        )

        Box(contentAlignment = Alignment.Center) {
            Canvas(modifier = Modifier.size(250.dp, 140.dp)) {

                if (path.isEmpty) {
                    path.addRoundRect(
                        RoundRect(
                            Rect(offset = Offset.Zero, size),
                            cornerRadius = CornerRadius(100.dp.toPx(), 100.dp.toPx())
                        )
                    )
                }
                pathWithProgress.reset()

                pathMeasure.setPath(path, forceClosed = false)
                pathMeasure.getSegment(
                    startDistance = 0f,
                    stopDistance = pathMeasure.length * progress / 100f,
                    pathWithProgress,
                    startWithMoveTo = true
                )


                clipPath(path) {
                    drawRect(Color.LightGray)
                }

                drawPath(
                    path = path,
                    style = Stroke(
                        6.dp.toPx()
                    ),
                    color = Color.Gray
                )

                drawPath(
                    path = pathWithProgress,
                    style = Stroke(
                        6.dp.toPx()
                    ),
                    color = Color.Blue
                )
            }

            Text(text = "$currentTime", fontSize = 40.sp, color = Color.Blue)
        }

        Spacer(modifier = Modifier.height(20.dp))
        Box(contentAlignment = Alignment.Center) {
            Canvas(modifier = Modifier.size(250.dp, 140.dp)) {

                if (path.isEmpty) {
                    path.addRoundRect(
                        RoundRect(
                            Rect(offset = Offset.Zero, size),
                            cornerRadius = CornerRadius(100.dp.toPx(), 100.dp.toPx())
                        )
                    )
                }
                pathWithProgress.reset()

                pathMeasure.setPath(path, forceClosed = false)
                pathMeasure.getSegment(
                    startDistance = 0f,
                    stopDistance = pathMeasure.length * progress.toInt() / 100f,
                    pathWithProgress,
                    startWithMoveTo = true
                )


                clipPath(path) {
                    drawRect(Color.LightGray)
                }

                drawPath(
                    path = path,
                    style = Stroke(
                        6.dp.toPx()
                    ),
                    color = Color.Gray
                )

                drawPath(
                    path = pathWithProgress,
                    style = Stroke(
                        6.dp.toPx()
                    ),
                    color = Color.Blue
                )
            }

            Text(text = "$currentTime", fontSize = 40.sp, color = Color.Blue)
        }

        Spacer(modifier = Modifier.height(20.dp))
        Box(contentAlignment = Alignment.Center) {
            Canvas(modifier = Modifier.size(250.dp, 140.dp)) {

                if (path.isEmpty) {
                    path.addRoundRect(
                        RoundRect(
                            Rect(offset = Offset.Zero, size),
                            cornerRadius = CornerRadius(100.dp.toPx(), 100.dp.toPx())
                        )
                    )
                }
                pathWithProgress.reset()

                pathMeasure.setPath(path, forceClosed = false)
                pathMeasure.getSegment(
                    startDistance = 0f,
                    stopDistance = pathMeasure.length * ((currentTime.toFloat() / startDurationInSeconds)),
                    pathWithProgress,
                    startWithMoveTo = true
                )


                clipPath(path) {
                    drawRect(Color.LightGray)
                }

                drawPath(
                    path = path,
                    style = Stroke(
                        6.dp.toPx()
                    ),
                    color = Color.Gray
                )

                drawPath(
                    path = pathWithProgress,
                    style = Stroke(
                        6.dp.toPx()
                    ),
                    color = Color.Blue
                )
            }

            Text(text = "$currentTime", fontSize = 40.sp, color = Color.Blue)
        }

        Button(
            modifier = Modifier.fillMaxWidth(),
            onClick = {
                targetValue = 0f
                timerStarted = true
            }) {
            Text(text = "Start Timer")
        }

        Text(
            text = "currentTime: $currentTime, " +
                    "progress: ${progress.toInt()}"
        )

    }
}
Etra answered 15/3, 2023 at 17:1 Comment(2)
The result is very commendable for your understanding. Can you share this drawing on github for me?Teakettle
@Đốc.tc here you go. github.com/SmartToolFactory/Jetpack-Compose-Tutorials/blob/…Etra

© 2022 - 2024 — McMap. All rights reserved.