1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Android】KotlinのCountDownTimerを用いた時分秒タイマー

Last updated at Posted at 2022-05-11

はじめに

今回はKotlinのライブラリCountDownTimerを用いて、より実用性の高いタイマーを作りました。
時分秒表示やストップボタン、リセットボタンを実装してあります。
参考:CountDownTimer公式ドキュメント

ソースコードはこちらから

Screenshot_20220512_015704.png

環境

  • Android Studio Bumblebee | 2021.1.1.patch3
  • targetSDK: 32

概要

  1. View Bindingの設定
  2. レイアウトの作成
  3. 初期状態の作成
  4. スタートボタンの作成
  5. ストップボタン、リセットボタンの作成
  6. 完成

1. View Bindingの設定

build.gradleのandroidに以下のコードを追加します

build.gradle
    kotlinOptions {
        jvmTarget = '1.8'
    }
    //ここから
    buildFeatures{
        viewBinding true
    }

MainActivity.ktに以下のコードを追加します

MainActivity.kt
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater).apply { setContentView(this.root) }
    }
}

これでView Bindingの設定は終わりです。

2. レイアウトの作成

レイアウトはシンプルにテキストビュー1つとボタン3つにします。

activity_main.xml
<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=".MainActivity">

    <TextView
        android:id="@+id/time_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="240dp"
        android:text="00"
        android:textSize="60sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/start_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="スタート"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/time_text_view" />

    <Button
        android:id="@+id/stop_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="ストップ"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/start_button" />

    <Button
        android:id="@+id/reset_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="リセット"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/stop_button" />
</androidx.constraintlayout.widget.ConstraintLayout>

3. 初期状態の作成

時間、分、秒を設定しテキストビューに表示します。
この際見やすいようにpadStartメソッドを使用して0埋めを行いました。

MainActivity.kt
        binding = ActivityMainBinding.inflate(layoutInflater).apply { setContentView(this.root) }

        //ここから
        val hour:Long = 0
        val minute:Long = 5
        val second:Long = 0

        binding.timeTextView.text = "${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}"

        var secondAll: Long = hour * 3600 + minute * 60 + second

        binding.stopButton.isVisible = false

4. スタートボタンの作成

スタートボタンのクリックリスナーを実行します。この際CountDownTimerを定義しますが、他のクリックリスナーでも使うのでlateinitで先に定義しておいてください。

MainActivity.kt
    private lateinit var binding: ActivityMainBinding
    private  lateinit var timer: CountDownTimer //ここを追加

    ~

        binding.stopButton.isVisible = false
        //ここから
        binding.startButton.setOnClickListener {
            binding.startButton.isVisible = false
            binding.stopButton.isVisible = true
            timer = object : CountDownTimer(secondAll * 1000, 1000) {
                override fun onFinish() {
                    binding.startButton.isVisible = true
                    secondAll = hour * 3600 + minute * 60 + second
                    binding.timeTextView.text = "${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}"
                }

                override fun onTick(millisUntilFinished: Long) {
                    secondAll--
                    binding.timeTextView.text = "${(secondAll / 3600).toString().padStart(2, '0')}:${((secondAll % 3600) / 60).toString().padStart(2, '0')}:${((secondAll % 3600) % 60).toString().padStart(2, '0')}"
                }
            }
            timer.start()
        }

5. ストップボタン、リセットボタンの作成

残り2つのボタンの処理も実装します。

MainActivity.kt
        binding.stopButton.setOnClickListener {
            binding.startButton.isVisible = true
            binding.stopButton.isVisible = false
            timer.cancel()
        }

        binding.resetButton.setOnClickListener {
            timer.cancel()
            binding.startButton.isVisible = true
            binding.stopButton.isVisible = false
            binding.timeTextView.text = "${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}"
            secondAll = hour * 3600 + minute * 60 + second
        }

6. 完成

あとはお好みでエディットテキストを用いて設定時間を変更できるようにしたり、終了時に音が鳴るようにするなど。
余談ですがCountDownTimerは誤差が大きく、正確な時間を測るには向いていないそう...
非同期処理を用いると良いそうなのでいつかちゃんと書きたい

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?