最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

kotlin - Using Jetpack Compose, how do you create an arc that decreases in length when a timer value decreases? - Stack Overflow

programmeradmin4浏览0评论

Using Jetpack Compose, I'm trying to create an animated arc. The animation that occurs involves the sweep angle of the arc decreasing in size when the value of a timer decreases. This is a pretty common animation, for example just look at the timer app on your phone.

Despite it's common use I still can't figure out how to implement it. I have successfully developed a feature where the arc sweep angle animates down but it only starts at 360 degrees if the timer is equal to 100. If the time starts at less than 100 than the sweep angle will be less than 360.

I need the sweep angle to start at 360 regardless of the starting time. Here is the code

Column(
modifier = Modifier.fillMaxSize()
){

var time by remember { mutableIntStateOf(100) }

var sweepAngle by mutableFloatStateOf(360f)

val animatedSweepAngle = animateFloatAsState(
       targetValue = countDownTimerSweepAngle,
   )

// Function That Starts The Timer
LaunchedEffect(time){
    while (playTime > 0) {
        time --
        sweepAngle = (time / 100f) * 360
        delay(1000)
        }
}

// Time
Text(text = time.toString())

// Arc
Box(
    modifier = Modifier
        .size(100.dp)
        .background(black)
        .drawBehind{
             drawArc(
                color = white,
                startAngle = 90f,
                sweepAngle = animatedSweepAngle.value,
                useCenter = false,
                style = Stroke(
                    width = 3.dp.toPx(),
                    cap = StrokeCap.Round
                   )
                )
            }
    )

}

If you run this code everything works fine but if you change the value of the time then it will fall apart. How do I fix this? Thanks

Using Jetpack Compose, I'm trying to create an animated arc. The animation that occurs involves the sweep angle of the arc decreasing in size when the value of a timer decreases. This is a pretty common animation, for example just look at the timer app on your phone.

Despite it's common use I still can't figure out how to implement it. I have successfully developed a feature where the arc sweep angle animates down but it only starts at 360 degrees if the timer is equal to 100. If the time starts at less than 100 than the sweep angle will be less than 360.

I need the sweep angle to start at 360 regardless of the starting time. Here is the code

Column(
modifier = Modifier.fillMaxSize()
){

var time by remember { mutableIntStateOf(100) }

var sweepAngle by mutableFloatStateOf(360f)

val animatedSweepAngle = animateFloatAsState(
       targetValue = countDownTimerSweepAngle,
   )

// Function That Starts The Timer
LaunchedEffect(time){
    while (playTime > 0) {
        time --
        sweepAngle = (time / 100f) * 360
        delay(1000)
        }
}

// Time
Text(text = time.toString())

// Arc
Box(
    modifier = Modifier
        .size(100.dp)
        .background(black)
        .drawBehind{
             drawArc(
                color = white,
                startAngle = 90f,
                sweepAngle = animatedSweepAngle.value,
                useCenter = false,
                style = Stroke(
                    width = 3.dp.toPx(),
                    cap = StrokeCap.Round
                   )
                )
            }
    )

}

If you run this code everything works fine but if you change the value of the time then it will fall apart. How do I fix this? Thanks

Share Improve this question asked Feb 15 at 5:00 Bob RasnerBob Rasner 2851 silver badge8 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Your issue is that the sweepAngle calculation depends on time / 100f * 360, which assumes time starts at 100. If time starts at a different value (e.g., 50), the initial sweepAngle is not 360.

Instead of hardcoding 100 as the full time, you should dynamically base the sweepAngle calculation on the initial time value.

I think this would resolve your issue:

@Composable
fun TimerArcScreen(startingTime: Int) {
   var time by remember { mutableIntStateOf(startingTime) }
   val totalTime = startingTime // Store the initial time to normalize progress

   var sweepAngle by remember { mutableFloatStateOf(360f) }

   // Animate the sweep angle smoothly
   val animatedSweepAngle by animateFloatAsState(
    targetValue = sweepAngle,
    animationSpec = tween(durationMillis = 500, easing = LinearEasing)
)

// Function That Starts The Timer
LaunchedEffect(time) {
    while (time > 0) {
        time--
        sweepAngle = (time / totalTime.toFloat()) * 360f // Normalize based on the starting time
        delay(1000)
    }
}

Column(
    modifier = Modifier.fillMaxSize(),
    verticalArrangement = Arrangement.Center
) {
    // Time Display
    Text(text = time.toString(), style = MaterialTheme.typography.headlineMedium)

    // Arc
    Box(
        modifier = Modifier
            .size(150.dp)
    ) {
        Canvas(modifier = Modifier.fillMaxSize()) {
            drawArc(
                color = Color.White,
                startAngle = 270f, // Start from the top
                sweepAngle = animatedSweepAngle,
                useCenter = false,
                style = Stroke(
                    width = 8.dp.toPx(),
                    cap = StrokeCap.Round
                )
            )
        }
    }
}

}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论