diff --git a/app/build.gradle b/app/build.gradle
index 5ad72cd..8beadf1 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -8,7 +8,7 @@ android {
defaultConfig {
applicationId "iam.thevoid.epic.timeapp"
- minSdk 21
+ minSdk 26
targetSdk 31
versionCode 1
versionName "1.0"
diff --git a/app/src/main/java/iam/thevoid/epic/timeapp/MainActivity.kt b/app/src/main/java/iam/thevoid/epic/timeapp/MainActivity.kt
index d08be6e..df2a40c 100644
--- a/app/src/main/java/iam/thevoid/epic/timeapp/MainActivity.kt
+++ b/app/src/main/java/iam/thevoid/epic/timeapp/MainActivity.kt
@@ -1,10 +1,20 @@
package iam.thevoid.epic.timeapp
-import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
+import android.util.Log
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
+import androidx.appcompat.app.AppCompatActivity
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
+import io.reactivex.rxjava3.core.Observable
+import io.reactivex.rxjava3.schedulers.Schedulers
+import java.time.Instant
+import java.time.LocalTime
+import java.time.format.DateTimeFormatter
+import java.util.concurrent.TimeUnit
+import kotlin.time.DurationUnit
+import kotlin.time.toDuration
// Дан экран с готовой разметкой
// Реализовать при помощи RxJava
@@ -28,19 +38,21 @@ import android.widget.TextView
class MainActivity : AppCompatActivity() {
+ private val TAG = this::class.simpleName
+
// Часы:
private lateinit var clockText: TextView
// Обратный отсчёт
- private lateinit var countdownText: TextView
- private lateinit var countdownSecondsEditText: EditText
- private lateinit var countdownStartButton: Button
+ private lateinit var countDownText: TextView
+ private lateinit var countDownSecondsEditText: EditText
+ private lateinit var countDownStartButton: Button
// Секундомер
- private lateinit var stopwatchText: TextView
- private lateinit var stopwatchMillisText: TextView
- private lateinit var stopwatchStartButton: EditText
- private lateinit var stopwatchEndButton: EditText
+ private lateinit var stopWatchText: TextView
+ private lateinit var stopWatchMillisText: TextView
+ private lateinit var stopWatchStartButton: Button
+ private lateinit var stopWatchEndButton: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -48,13 +60,151 @@ class MainActivity : AppCompatActivity() {
clockText = findViewById(R.id.clockText)
- countdownText = findViewById(R.id.countdownText)
- countdownSecondsEditText = findViewById(R.id.countdownEditText)
- countdownStartButton = findViewById(R.id.countdownStartButton)
+ countDownText = findViewById(R.id.countdownText)
+ countDownSecondsEditText = findViewById(R.id.countdownEditText)
+ countDownStartButton = findViewById(R.id.countdownStartButton)
+
+ stopWatchText = findViewById(R.id.stopwatchText)
+ stopWatchMillisText = findViewById(R.id.stopwatchMillisText)
+ stopWatchStartButton = findViewById(R.id.stopwatchStartButton)
+ stopWatchEndButton = findViewById(R.id.stopwatchEndButton)
+
+
+ // 1. Часы
+ clock()
+
+ // 2. Таймер
+ displayCountDown(0) // Начальное значение
+ timer()
+
+
+ // 3. Секундомер
+ displayStopWatch() // Начальное значение
+ stopWatch()
+ }
+
+ private fun clock() {
+ Observable.interval(1, TimeUnit.SECONDS, Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+
+ .subscribe {
+ clockText.text = LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"))
+ }
+ }
+
+ private val delimiter = ":"
+
+ private val twoDigits: (Number) -> String =
+ { value -> if (value.toLong() < 10) "0$value" else "$value" }
+
+ private val formatTime: (Long, Int, Int, Int) -> java.lang.StringBuilder =
+ { hours, minutes, seconds, nano ->
+ StringBuilder()
+ .append(twoDigits(hours))
+ .append(delimiter)
+ .append(twoDigits(minutes))
+ .append(delimiter)
+ .append(twoDigits(seconds))
+ }
+
+ private val displayCountDown: (Long) -> Unit =
+ { seconds ->
+ countDownText.text =
+ seconds.toDuration(DurationUnit.SECONDS).toComponents(formatTime)
+ }
+
+ private fun timer() {
+ val countDownValue: () -> Long =
+ { countDownSecondsEditText.text.toString().toLongOrNull() ?: 0L }
+
+ countDownStartButton.setOnClickListener {
+ val seconds = countDownValue()
+ Log.i(TAG, "seconds: $seconds")
+
+ if (seconds > 0) {
+ // Время окончания
+ val end = Instant.now().plusSeconds(seconds)
+
+ Observable.interval(1, TimeUnit.SECONDS, Schedulers.computation())
+ .observeOn(AndroidSchedulers.mainThread())
+
+ .takeWhile { Instant.now() <= end }
+
+ .subscribe {
+ val remained = end.minusMillis(Instant.now().toEpochMilli())
+ val duration =
+ remained.toEpochMilli().toDuration(DurationUnit.MILLISECONDS)
+ countDownText.text = duration.toComponents(formatTime)
+ }
+ }
+ }
+ }
+
+ private enum class EStopWatchStatus {
+ STOP,
+ RUN,
+ PAUSE
+ }
+
+ private object stopWatchStatus {
+ var status: EStopWatchStatus = EStopWatchStatus.STOP
+ var value: Long = 0
+ }
+
+ private val displayStopWatch: () -> Unit = {
+ stopWatchText.text =
+ stopWatchStatus.value.toDuration(DurationUnit.MILLISECONDS)
+ .toComponents(formatTime)
+ stopWatchMillisText.text =
+ "${stopWatchStatus.value % 1000 / 100}" // 10-е мс
+ }
+
+ private fun stopWatch() {
+ stopWatchStartButton.setOnClickListener {
+ Log.i(TAG, "${stopWatchStatus.status}: ${stopWatchStatus.value}")
+
+ if (stopWatchStatus.status == EStopWatchStatus.STOP || stopWatchStatus.status == EStopWatchStatus.PAUSE) {
+ stopWatchStatus.status = EStopWatchStatus.RUN // Начинаем работу
+
+ stopWatchEndButton.text = "Пауза"
+
+ val start = Instant.now()
+ .toEpochMilli() - stopWatchStatus.value // При состоянии паузы "отходим назад"
+
+ Observable.interval(100, TimeUnit.MILLISECONDS, Schedulers.computation())
+ .observeOn(AndroidSchedulers.mainThread())
+
+ .takeWhile { stopWatchStatus.status == EStopWatchStatus.RUN }
+
+ .subscribe {
+ stopWatchStatus.value = Instant.now().toEpochMilli() - start
+ displayStopWatch()
+ }
+ }
+ }
+
+ stopWatchEndButton.setOnClickListener()
+ {
+ Log.i(TAG, "${stopWatchStatus.status}: ${stopWatchStatus.value}")
+ when (stopWatchStatus.status) {
+ EStopWatchStatus.RUN -> {
+ // Приостанавливаем
+ stopWatchStatus.status = EStopWatchStatus.PAUSE
+ stopWatchEndButton.text = "Сброс"
+ }
+ EStopWatchStatus.PAUSE -> {
+ // Сброс
+ stopWatchStatus.status = EStopWatchStatus.STOP
+ stopWatchStatus.value = 0
+
+ stopWatchEndButton.text = "Пауза"
- stopwatchText = findViewById(R.id.stopwatchText)
- stopwatchMillisText = findViewById(R.id.stopwatchMillisText)
- stopwatchStartButton = findViewById(R.id.stopwatchStartButton)
- stopwatchEndButton = findViewById(R.id.stopwatchEndButton)
+ displayStopWatch()
+ }
+ EStopWatchStatus.STOP -> {
+ stopWatchEndButton.text = "Пауза"
+ }
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 81ade1e..e395997 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -65,7 +65,7 @@
android:id="@+id/countdownStartButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="Start" />
+ android:text="Старт" />
+ android:text="Старт" />
+ android:text="Пауза" />
diff --git a/build.gradle b/build.gradle
index 84ed49d..0ccd671 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
- id 'com.android.application' version '7.1.1' apply false
- id 'com.android.library' version '7.1.1' apply false
+ id 'com.android.application' version '7.1.2' apply false
+ id 'com.android.library' version '7.1.2' apply false
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}