Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save iniyanmurugavel/573157a89d9ae88bb2024efbb8ed8c0d to your computer and use it in GitHub Desktop.

Select an option

Save iniyanmurugavel/573157a89d9ae88bb2024efbb8ed8c0d to your computer and use it in GitHub Desktop.

Revisions

  1. @Kyriakos-Georgiopoulos Kyriakos-Georgiopoulos revised this gist May 31, 2025. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions CountdownScreen.kt
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,11 @@
    internal data class GameCountdownState(
    data class GameCountdownState(
    val durationMills: Int = 3000,
    val circleColor: Color = Color.Yellow,
    val textColor: Color = Color.Yellow
    )

    Composable
    internal fun CountdownScreen(
    fun CountdownScreen(
    state: GameCountdownState,
    onFinish: () -> Unit,
    ) {
    @@ -84,7 +84,7 @@ fun AnimateCircle(
    }

    @Composable
    internal fun CountdownText(
    fun CountdownText(
    durationMills: Int,
    color: Color,
    onFinish: (() -> Unit)? = null,
  2. @Kyriakos-Georgiopoulos Kyriakos-Georgiopoulos revised this gist May 31, 2025. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion CountdownScreen.kt
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    data class GameCountdownState(
    internal data class GameCountdownState(
    val durationMills: Int = 3000,
    val circleColor: Color = Color.Yellow,
    val textColor: Color = Color.Yellow
  3. @Kyriakos-Georgiopoulos Kyriakos-Georgiopoulos renamed this gist May 31, 2025. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  4. @Kyriakos-Georgiopoulos Kyriakos-Georgiopoulos created this gist May 31, 2025.
    114 changes: 114 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,114 @@
    data class GameCountdownState(
    val durationMills: Int = 3000,
    val circleColor: Color = Color.Yellow,
    val textColor: Color = Color.Yellow
    )

    Composable
    internal fun CountdownScreen(
    state: GameCountdownState,
    onFinish: () -> Unit,
    ) {

    AnimateCircle(
    durationMills = state.durationMills,
    circleColor = state.circleColor,
    )

    Box(
    contentAlignment = Alignment.Center,
    ) {
    CountdownText(
    durationMills = state.durationMills,
    color = state.textColor,
    onFinish = onFinish,
    )
    }
    }

    @Composable
    fun AnimateCircle(
    durationMills: Int,
    circleColor: Color,
    ) {
    var startTransition by remember {
    mutableStateOf(false)
    }
    LaunchedEffect(Unit) {
    startTransition = true
    }

    val progress: Float by animateFloatAsState(
    targetValue = if (startTransition) 1f else 0f,
    animationSpec = tween(
    durationMillis = durationMills,
    easing = LinearEasing,
    ),
    label = "circleProgress",
    )

    Canvas(
    modifier = Modifier.fillMaxSize(),
    ) {

    val radius = 100.dp.toPx()
    val center = Offset(
    x = (size.width / 2) - radius,
    y = size.height / 2 - radius,
    )

    drawArc(
    color = circleColor,
    startAngle = -90f,
    sweepAngle = 360 * progress,
    useCenter = false,
    size = Size(
    width = radius * 2,
    height = radius * 2,
    ),
    topLeft = center,
    style = Stroke(width = 8.dp.toPx()),
    )

    drawCircle(
    color = Color.White,
    alpha = 0.25f,
    center = Offset(
    x = size.width / 2,
    y = size.height / 2,
    ),
    radius = radius,
    style = Stroke(width = 8.dp.toPx()),
    )
    }
    }

    @Composable
    internal fun CountdownText(
    durationMills: Int,
    color: Color,
    onFinish: (() -> Unit)? = null,
    ) {
    var timeLeftInMillis by remember(durationMills) {
    mutableIntStateOf(durationMills)
    }

    LaunchedEffect(durationMills) {
    launch {
    while (timeLeftInMillis > 0) {
    delay(1000)
    timeLeftInMillis -= 1000
    }
    onFinish?.invoke()
    }
    }
    val seconds = (timeLeftInMillis / 1000 % 60)

    Text(
    modifier = Modifier
    .padding(16.dp),
    text = seconds.toString(),
    textAlign = TextAlign.Center,
    style = TextStyle(color = color, fontSize = 72.sp),
    )
    }