How to create a simple countdown timer in Kotlin?

Solution 1:

You can use Kotlin objects:

val timer = object: CountDownTimer(20000, 1000) {
    override fun onTick(millisUntilFinished: Long) {...}

    override fun onFinish() {...}
}
timer.start()

Solution 2:

I've solved my problem with timer in Kotlin like this:

class Timer {

    private val job = SupervisorJob()
    private val scope = CoroutineScope(Dispatchers.Default + job)

    private fun startCoroutineTimer(delayMillis: Long = 0, repeatMillis: Long = 0, action: () -> Unit) = scope.launch(Dispatchers.IO) {
        delay(delayMillis)
        if (repeatMillis > 0) {
            while (true) {
                action()
                delay(repeatMillis)
            }
        } else {
            action()
        }
    }

    private val timer: Job = startCoroutineTimer(delayMillis = 0, repeatMillis = 20000) {
        Log.d(TAG, "Background - tick")
        doSomethingBackground()
        scope.launch(Dispatchers.Main) {
            Log.d(TAG, "Main thread - tick")
            doSomethingMainThread()
        }
    }

    fun startTimer() {
        timer.start()
    }

    fun cancelTimer() {
        timer.cancel()
    }
//...
}

I've used Coroutines for a timer.

Solution 3:

Chronometer can be set to count down and it seems to me the easiest way.

Add the Chronometer view in your layout xml, example

<Chronometer  
 android:id="@+id/view_timer"   
 tools:targetApi="24"  
 android:layout_width="wrap_content"  
 android:layout_height="wrap_content"/>

Then in your activity or fragment:

   view_timer.isCountDown = true
   view_timer.base = SystemClock.elapsedRealtime() + 20000
   view_timer.start()

Solution 4:

If you want to show a countdown with days hours minutes and seconds

private lateinit var countDownTimer:CountDownTimer
.
.
.
    fun printDifferenceDateForHours() {

            val currentTime = Calendar.getInstance().time
            val endDateDay = "03/02/2020 21:00:00"
            val format1 = SimpleDateFormat("dd/MM/yyyy hh:mm:ss",Locale.getDefault())
            val endDate = format1.parse(endDateDay)

            //milliseconds
            var different = endDate.time - currentTime.time
            countDownTimer = object : CountDownTimer(different, 1000) {

                override fun onTick(millisUntilFinished: Long) {
                    var diff = millisUntilFinished
                    val secondsInMilli: Long = 1000
                    val minutesInMilli = secondsInMilli * 60
                    val hoursInMilli = minutesInMilli * 60
                    val daysInMilli = hoursInMilli * 24

                    val elapsedDays = diff / daysInMilli
                    diff %= daysInMilli

                    val elapsedHours = diff / hoursInMilli
                    diff %= hoursInMilli

                    val elapsedMinutes = diff / minutesInMilli
                    diff %= minutesInMilli

                    val elapsedSeconds = diff / secondsInMilli

                    txt_timeleft.text = "$elapsedDays days $elapsedHours hs $elapsedMinutes min $elapsedSeconds sec"
                }

                override fun onFinish() {
                    txt_timeleft.text = "done!"
                }
            }.start()
        }

If you are navigating to another activity/fragment, make sure to cancel the countdown

countDownTimer.cancel()

Code output

51 days 17 hs 56 min 5 sec

Solution 5:

Try to use objects, like this :

var countDownTimer = object : CountDownTimer(2000, 1000) {
    // override object functions here, do it quicker by setting cursor on object, then type alt + enter ; implement members
}

Try this website : https://try.kotlinlang.org/#/Kotlin%20Koans/Introduction/Java%20to%20Kotlin%20conversion/Task.kt

You have a little button "Convert from Java" on the top right that could be useful to you.

EDIT:

Do not forget to start this object when you need it, by adding .start() at the end of the declaration, or wherever in your activity / fragment :

countDownTimer.start()