숨참고 개발다이브

[안드로이드/kotlin] 특정 날짜까지 남은 시간 타이머 만들기(CountDownTimer) 본문

개발/Android

[안드로이드/kotlin] 특정 날짜까지 남은 시간 타이머 만들기(CountDownTimer)

사라 Sarah 2022. 5. 31. 11:41
728x90

 

CountDownTimer는 별도의 Thread를 생성하여 처리하지 않아도 간편하게 타이머 기능을 만들 수 있는 클래스다.

 

공식 문서를 통해 생성자와 기본 함수들을 확인할 수 있다.

함수명들이 굉장히 직관적이기 때문에 따로 설명을 하지 않아도 이해할 수 있다.

 

 

CountDownTimer는 두 개의 파라미터를 받는다.

- millisInFuture : 타이머의 작동 시간의 밀리초 값. 종료시간 - 시작시간 의 밀리값을 넣으면 된다.

- coundDownInterval : onTick()의 호출 간격. 단위는 마찬가지로 밀리초이기 때문에 1초 간격을 설정하고 싶다면 1000을 넣어야 한다.

 

 

먼저 종료 시점을 임의로 생성해준다.

val deadLine = Calendar.getInstance()
deadLine.add(Calendar.DAY_OF_MONTH, 1)
deadLine.add(Calendar.HOUR, 9)
deadLine.add(Calendar.MINUTE, 28)

 

종료시각의 밀리초 - 현재시각의 밀리초 를 계산하여 남은 시간을 구한다.

val diffSec: Long = (deadLine.timeInMillis - Calendar.getInstance().timeInMillis)

 

 

 

onTick()이 실행되는 간격을 1초로 설정하고 생성해준다. 또한 start()를 호출해 타이머를 바로 시작해준다.

화면 진입 시 바로 타이머를 실행시킬게 아니라면 start() 의 위치를 특정 이벤트 호출 시로 바꾸어주면 된다.

mTimer = object : CountDownTimer(diffSec, 1000) {
    override fun onTick(millisUntilFinished: Long) {
        mBinding.textTimer.text = getTime( deadLine )
    }
    override fun onFinish() {
        // CountDown가 종료될 때 화면종료, intent 등을 넣어준다.
    }
}
mTimer.start()

 

남은 시간을 String으로 만드는 함수

private fun getTime( deadLine: Calendar ): String? {
    val diffSec: Long = (deadLine.timeInMillis - Calendar.getInstance().timeInMillis) / 1000
    val hourTime = floor((diffSec / 3600).toDouble()).toInt()
    val minTime = floor(((diffSec - 3600 * hourTime) / 60).toDouble()).toInt()
    val secTime = floor((diffSec - 3600 * hourTime - 60 * minTime).toDouble()).toInt()
    if ( hourTime <= 0 && minTime <= 0 && secTime <= 0 )
        return ""
    val hour = String.format("%02d", hourTime)
    val min = String.format("%02d", minTime)
    val sec = String.format("%02d", secTime)
    return "$hour:$min:$sec"
}

 

 

 

 

코드 전체

 

TimerActivity.kt

class TimerActivity : AppCompatActivity() {

    private val TAG = TimerActivity::class.java.name

    private lateinit var mBinding: ActivityTimerBinding
    private lateinit var mTimer: CountDownTimer

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        mBinding = ActivityTimerBinding.inflate(layoutInflater)
        setContentView(mBinding.root)

        val deadLine = Calendar.getInstance()
        deadLine.add(Calendar.DAY_OF_MONTH, 1)
        deadLine.add(Calendar.HOUR, 9)
        deadLine.add(Calendar.MINUTE, 28)

        val strDeadline = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(deadLine.time)
        mBinding.textDeadline.text = "$strDeadline 까지 남은 시간"

        val diffSec: Long = (deadLine.timeInMillis - Calendar.getInstance().timeInMillis)

        mTimer = object : CountDownTimer(diffSec, 1000) {
            override fun onTick(millisUntilFinished: Long) {
                mBinding.textTimer.text = getTime( deadLine )
            }

            override fun onFinish() {
                // CountDown가 종료될 때
            }
        }

        mTimer.start()
    }


    private fun getTime( deadLine: Calendar ): String? {

        val diffSec: Long = (deadLine.timeInMillis - Calendar.getInstance().timeInMillis) / 1000

        val hourTime = floor((diffSec / 3600).toDouble()).toInt()
        val minTime = floor(((diffSec - 3600 * hourTime) / 60).toDouble()).toInt()
        val secTime = floor((diffSec - 3600 * hourTime - 60 * minTime).toDouble()).toInt()

        if ( hourTime <= 0 && minTime <= 0 && secTime <= 0 )
            return ""

        val hour = String.format("%02d", hourTime)
        val min = String.format("%02d", minTime)
        val sec = String.format("%02d", secTime)

        return "$hour:$min:$sec"
    }

}

 

activity_timer.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".TimerActivity">

    <TextView
        android:id="@+id/text_deadline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="26dp"
        android:textColor="@color/black"

        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <LinearLayout
        android:id="@+id/linear_change"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="60dp"
        android:gravity="center"
        android:orientation="horizontal"

        android:layout_marginHorizontal="55dp"
        android:layout_marginTop="26dp"
        android:layout_marginBottom="20dp"
        android:elevation="8dp"

        android:background="@drawable/box_white_radius_4_outline_light_dee2e6"
        android:foreground="?attr/selectableItemBackground"

        app:layout_constraintTop_toBottomOf="@id/text_deadline" >

        <TextView
            android:id="@+id/text_timer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/black"
            android:textSize="25sp"
            android:textStyle="bold" />

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

 

300x250
Comments