はじめに
今回はKotlinのライブラリCountDownTimerを用いて、より実用性の高いタイマーを作りました。
時分秒表示やストップボタン、リセットボタンを実装してあります。
参考:CountDownTimer公式ドキュメント
ソースコードはこちらから
環境
- Android Studio Bumblebee | 2021.1.1.patch3
- targetSDK: 32
概要
- View Bindingの設定
- レイアウトの作成
- 初期状態の作成
- スタートボタンの作成
- ストップボタン、リセットボタンの作成
- 完成
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は誤差が大きく、正確な時間を測るには向いていないそう...
非同期処理を用いると良いそうなのでいつかちゃんと書きたい