From 3b9001f522d4831432a41762be70a400c265166f Mon Sep 17 00:00:00 2001 From: "yaroslav.budanov" Date: Tue, 29 Mar 2022 16:10:28 +0300 Subject: [PATCH 1/2] =?UTF-8?q?=D0=94=D0=97=202=20:=20=D0=91=D1=83=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=AF=D1=80=D0=BE=D1=81=D0=BB=D0=B0?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iam/thevoid/epic/timeapp/MainActivity.kt | 138 +++++++++++++++++- 1 file changed, 136 insertions(+), 2 deletions(-) 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..2e35b5c 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 android.graphics.Color 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 io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.core.* +import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.schedulers.Schedulers +import java.time.LocalTime +import java.time.format.DateTimeFormatter +import java.util.concurrent.TimeUnit +import java.time.temporal.ChronoUnit.MILLIS // Дан экран с готовой разметкой // Реализовать при помощи RxJava @@ -35,12 +45,18 @@ class MainActivity : AppCompatActivity() { private lateinit var countdownText: TextView private lateinit var countdownSecondsEditText: EditText private lateinit var countdownStartButton: Button + private var counter: Long = 0L // Секундомер private lateinit var stopwatchText: TextView private lateinit var stopwatchMillisText: TextView - private lateinit var stopwatchStartButton: EditText - private lateinit var stopwatchEndButton: EditText + private lateinit var stopwatchStartButton: Button + private lateinit var stopwatchEndButton: Button + private lateinit var stopwatchTime: LocalTime + private lateinit var stopwatchTimeBuf: LocalTime + + private var disposable: Disposable? = null + private var pause: Boolean = true override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -48,13 +64,131 @@ class MainActivity : AppCompatActivity() { clockText = findViewById(R.id.clockText) + Single.create { + it.onSuccess( + LocalTime + .now() + .format(DateTimeFormatter.ofPattern("HH:mm:ss")) + .toString() + ) + } + .delay(1, TimeUnit.SECONDS) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .repeat() + .subscribe { time -> + clockText.setText(time) + } + countdownText = findViewById(R.id.countdownText) countdownSecondsEditText = findViewById(R.id.countdownEditText) countdownStartButton = findViewById(R.id.countdownStartButton) + countdownStartButton.setOnClickListener { + if (!countdownSecondsEditText.text.isEmpty()) { + counter = countdownSecondsEditText.text.toString().toLong() + countdownText.setText(getElapsedCountDownTime(counter)) + + Flowable.fromIterable(1L..counter) + .concatMapCompletable { + Completable + .timer(1, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .doOnComplete { + val elapsedTime = counter - it; + countdownText.setText(getElapsedCountDownTime(elapsedTime)) + if (elapsedTime == 0L) { + countdownText.setBackgroundColor(Color.RED) + Completable.timer(3, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { + countdownText.setBackgroundColor(Color.WHITE) + } + } + } + } + .subscribe() + } + } + stopwatchText = findViewById(R.id.stopwatchText) stopwatchMillisText = findViewById(R.id.stopwatchMillisText) stopwatchStartButton = findViewById(R.id.stopwatchStartButton) stopwatchEndButton = findViewById(R.id.stopwatchEndButton) + clearStopwatchTime() + + stopwatchStartButton.setOnClickListener { + Log.d(LOG_TAG, "start timer") + if (!pause) + clearStopwatchTime() + stopwatchTimeBuf = LocalTime.now() + pause = false + + disposable = Flowable.interval(0, 1, TimeUnit.MILLISECONDS) + .subscribeOn(Schedulers.computation()) + .onBackpressureDrop() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + val now = LocalTime.now() + stopwatchTime = stopwatchTime.plus(stopwatchTimeBuf.until(now, MILLIS), MILLIS) + stopwatchTimeBuf = now + Log.d( + LOG_TAG, + (stopwatchTime.format( + DateTimeFormatter.ofPattern("HH:mm:ss.SSS") + ).toString()) + ) + Log.d(LOG_TAG, "time was changed") + setStopwatchTimeEdit() + }, + { + Log.d(LOG_TAG, it.message.orEmpty()) + } + ) + + } + + stopwatchEndButton.setOnClickListener { + disposable?.dispose() + disposable = null + if (pause) { + Log.d(LOG_TAG, "clear timer") + stopwatchStartButton.setText("START") + stopwatchEndButton.setText("PAUSE") + clearStopwatchTime() + } else { + Log.d(LOG_TAG, "pause timer") + stopwatchStartButton.setText("CONTINUE") + stopwatchEndButton.setText("CLEAR") + pause = true + } + } + } + + private fun getElapsedCountDownTime(counter: Long): String { + return LocalTime.of(0, 0, 0, 0) + .plusSeconds(counter) + .format(DateTimeFormatter.ofPattern("mm:ss")) + .toString() + } + + private fun clearStopwatchTime() { + stopwatchTime = LocalTime.of(0, 0, 0, 0) + setStopwatchTimeEdit() + } + + private fun setStopwatchTimeEdit() { + stopwatchText.setText( + stopwatchTime.format(DateTimeFormatter.ofPattern("HH:mm:ss")) + .toString() + ) + stopwatchMillisText.setText( + stopwatchTime.format(DateTimeFormatter.ofPattern(".SSS")).toString() + ) + } + + companion object { + private val LOG_TAG = MainActivity::class.simpleName } } \ No newline at end of file From e3aeab0043d66cdfc5fd8f8b553dc2bf9891084d Mon Sep 17 00:00:00 2001 From: "yaroslav.budanov" Date: Tue, 5 Apr 2022 19:13:13 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8:=201)?= =?UTF-8?q?=20=D0=92=20=D0=B1=D0=BB=D0=BE=D0=BA=D0=B5=20"=D0=9E=D0=B1?= =?UTF-8?q?=D1=80=D0=B0=D1=82=D0=BD=D1=8B=D0=B9=20=D0=BE=D1=82=D1=81=D1=87?= =?UTF-8?q?=D0=B5=D1=82"=20=D0=B5=D1=81=D0=BB=D0=B8=20=D1=83=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2=D0=B8=D1=82=D1=8C=2022=20=D1=81=D0=B5?= =?UTF-8?q?=D0=BA=D1=83=D0=BD=D0=B4=D1=8B,=20=D0=BD=D0=B0=D0=B6=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=20"=D0=A1=D1=82=D0=B0=D1=80=D1=82"=20=D0=B8=20?= =?UTF-8?q?=D0=BD=D0=B5=D0=B4=D0=BE=D0=B6=D0=B4=D0=B0=D0=B2=D1=88=D0=B8?= =?UTF-8?q?=D1=81=D1=8C=20=D0=B7=D0=B0=D0=B2=D1=80=D0=B5=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BE=D1=82=D1=81=D1=87=D0=B5=D1=82=D0=B0=20?= =?UTF-8?q?=D0=BD=D0=B0=D0=B6=D0=B0=D1=82=D1=8C=20"=D0=A1=D1=82=D0=B0?= =?UTF-8?q?=D1=80=D1=82"=20=D0=B5=D1=89=D0=B5=20=D1=80=D0=B0=D0=B7,=20?= =?UTF-8?q?=D1=82=D0=BE=20=D0=BD=D0=B0=20=D1=8D=D0=BA=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D0=B5=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D1=8F=D1=82?= =?UTF-8?q?=D1=8C=D1=81=D1=8F=20=D0=BD=D0=B5=D1=81=D0=BA=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=BA=D0=BE=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D0=B9?= =?UTF-8?q?=20=D0=BE=D0=B1=D0=BD=D0=B0=D1=82=D0=BD=D0=BE=D0=B3=D0=BE=20?= =?UTF-8?q?=D0=BE=D1=82=D1=81=D1=87=D0=B5=D1=82=D0=B0=20=D1=81=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=8F=D1=8E=D1=8E=20=D0=B4=D1=80=D1=83=D0=B3=20=D0=B4?= =?UTF-8?q?=D1=80=D1=83=D0=B3=D0=B0.=20=D0=94=D1=80=D1=83=D0=B3=D0=B8?= =?UTF-8?q?=D0=BC=D0=B8=20=D1=81=D0=BB=D0=BE=D0=B2=D0=B0=D0=BC=D0=B8,=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B5=D0=B4=D1=8B=D0=B4=D1=83=D1=89=D0=B5=D0=B5=20?= =?UTF-8?q?=D1=81=D0=BE=D1=81=D1=82=D0=BE=D1=8F=D0=BD=D0=B8=D0=B5=20=D1=81?= =?UTF-8?q?=D0=BE=D1=85=D1=80=D0=B0=D0=BD=D1=8F=D0=B5=D1=82=D1=81=D1=8F,?= =?UTF-8?q?=20=D0=B0=20=D0=BD=D0=B5=20=D1=81=D0=B1=D1=80=D0=B0=D1=81=D1=8B?= =?UTF-8?q?=D0=B2=D0=B0=D0=B5=D1=82=D1=81=D1=8F,=20=D0=BA=D0=B0=D0=BA=20?= =?UTF-8?q?=D0=BE=D0=B6=D0=B8=D0=B4=D0=B0=D0=B5=D1=82=D1=81=D1=8F.=202)=20?= =?UTF-8?q?=D0=92=20=D0=B1=D0=BB=D0=BE=D0=BA=D0=B5=20"=D0=A1=D0=B5=D0=BA?= =?UTF-8?q?=D1=83=D0=BD=D0=B4=D0=BE=D0=BC=D0=B5=D1=80"=20=D0=B5=D1=81?= =?UTF-8?q?=D0=BB=D0=B8=20=D0=BD=D0=B0=D0=B6=D0=B0=D1=82=D1=8C=20=D0=BD?= =?UTF-8?q?=D0=B0=20"=D0=A1=D1=82=D0=B0=D1=80=D1=82"=20=D0=BD=D0=B5=D1=81?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D1=80=D0=B0=D0=B7=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D1=80=D1=8F=D0=B4,=20=D0=B0=20=D0=B7=D0=B0?= =?UTF-8?q?=D1=82=D0=B5=D0=BC=20=D0=BD=D0=B0=D0=B6=D0=B0=D1=82=D1=8C=20?= =?UTF-8?q?=D0=BD=D0=B0=20"=D0=9F=D0=B0=D1=83=D0=B7=D0=B0",=20=D1=82=D0=BE?= =?UTF-8?q?=20=D1=81=D1=87=D0=B5=D1=82=20=D0=BD=D0=B5=20=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B0=D0=BD=D0=B0=D0=B2=D0=BB=D0=B8=D0=B2?= =?UTF-8?q?=D0=B0=D0=B5=D1=82=D1=81=D1=8F,=20=D0=B0=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B4=D0=BE=D0=BB=D0=B6=D0=B0=D0=B5=D1=82=D1=81=D1=8F.=20?= =?UTF-8?q?=D0=A2=D0=B0=D0=BA=D0=B6=D0=B5=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=BD=D0=B0=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81=D1=87=D0=B5=D1=82=D0=B0=20(?= =?UTF-8?q?=D1=82=D0=B5=D0=BA=D1=81=D1=82=D0=B0)=20=D0=B2=D0=B8=D0=B7?= =?UTF-8?q?=D1=83=D0=BB=D1=8C=D0=BD=D0=BE=20"=D0=BF=D1=80=D0=B8=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=BC=D0=B0=D0=B6=D0=B8=D0=B2=D0=B0=D0=B5=D1=82?= =?UTF-8?q?=D1=81=D1=8F"=20(=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=20=D1=81=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BD=D0=B8=D1=82=D1=8C=20=D1=81=20=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=D0=BC=20?= =?UTF-8?q?=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D1=8F,=20=D0=B5?= =?UTF-8?q?=D1=81=D0=BB=D0=B8=20=D0=BD=D0=B0=D0=B6=D0=B0=D1=82=D1=8C=20?= =?UTF-8?q?=D0=BD=D0=B0=20"=D0=A1=D1=82=D0=B0=D1=80=D1=82"=20=D1=82=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=BA=D0=BE=201=20=D1=80=D0=B0=D0=B7).=203)=20?= =?UTF-8?q?=D0=92=20=D0=B1=D0=BB=D0=BE=D0=BA=D0=B5=20"=D0=A1=D0=B5=D0=BA?= =?UTF-8?q?=D1=83=D0=BD=D0=B4=D0=BE=D0=BC=D0=B5=D1=80"=20=D0=BD=D0=B0?= =?UTF-8?q?=D0=B6=D0=B0=D1=82=D1=8C=20=D0=BD=D0=B0=20"=D0=A1=D1=82=D0=B0?= =?UTF-8?q?=D1=80=D1=82",=20=D0=B7=D0=B0=D1=82=D0=B5=D0=BC=20=D0=BD=D0=B0?= =?UTF-8?q?=20"=D0=9F=D0=B0=D1=83=D0=B7=D0=B0"=20=D0=B8=20=D1=87=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B7=20=D0=BD=D0=B0=20"=D0=A1=D1=82=D0=B0=D1=80?= =?UTF-8?q?=D1=82".=20=D0=9E=D0=B6=D0=B8=D0=B4=D0=B0=D0=B5=D1=82=D1=81?= =?UTF-8?q?=D1=8F,=20=D1=87=D1=82=D0=BE=20=D1=82=D0=B5=D0=BA=D1=81=D1=82?= =?UTF-8?q?=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BE=D0=BA=20=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BD=D0=B5=D1=82=D1=81=D1=8F=20=D0=B2=20=D0=B8=D1=81=D1=85?= =?UTF-8?q?=D0=BE=D0=B4=D0=BD=D0=BE=D0=B5=20=D1=81=D0=BE=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D1=8F=D0=BD=D0=B8=D0=B5,=20=D0=BE=D0=B4=D0=BD=D0=B0=D0=BA?= =?UTF-8?q?=D0=BE,=20=D1=8D=D1=82=D0=BE=D0=B3=D0=BE=20=D0=BD=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B8=D1=81=D1=85=D0=BE=D0=B4=D0=B8=D1=82.?= =?UTF-8?q?=20=D0=A2=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=B5=D1=81=D0=BB?= =?UTF-8?q?=D0=B8=20=D0=BD=D0=B0=D0=B6=D0=B0=D1=82=D1=8C=20=D0=BD=D0=B0=20?= =?UTF-8?q?"=D0=9E=D1=87=D0=B8=D1=81=D1=82=D0=B8=D1=82=D1=8C".?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iam/thevoid/epic/timeapp/MainActivity.kt | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) 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 2e35b5c..6a7c41a 100644 --- a/app/src/main/java/iam/thevoid/epic/timeapp/MainActivity.kt +++ b/app/src/main/java/iam/thevoid/epic/timeapp/MainActivity.kt @@ -55,7 +55,8 @@ class MainActivity : AppCompatActivity() { private lateinit var stopwatchTime: LocalTime private lateinit var stopwatchTimeBuf: LocalTime - private var disposable: Disposable? = null + private var disposableCountdown: Disposable? = null + private var disposableStopwatch: Disposable? = null private var pause: Boolean = true override fun onCreate(savedInstanceState: Bundle?) { @@ -85,11 +86,16 @@ class MainActivity : AppCompatActivity() { countdownStartButton = findViewById(R.id.countdownStartButton) countdownStartButton.setOnClickListener { + if (disposableCountdown != null) { + disposableCountdown?.dispose() + disposableCountdown = null + countdownText.setText("") + } if (!countdownSecondsEditText.text.isEmpty()) { counter = countdownSecondsEditText.text.toString().toLong() countdownText.setText(getElapsedCountDownTime(counter)) - Flowable.fromIterable(1L..counter) + disposableCountdown = Flowable.fromIterable(1L..counter) .concatMapCompletable { Completable .timer(1, TimeUnit.SECONDS) @@ -119,19 +125,29 @@ class MainActivity : AppCompatActivity() { stopwatchStartButton.setOnClickListener { Log.d(LOG_TAG, "start timer") + if (disposableStopwatch != null) { + disposableStopwatch?.dispose() + disposableStopwatch = null + } + + stopwatchStartButton.setText("START") + stopwatchEndButton.setText("PAUSE") + if (!pause) clearStopwatchTime() + stopwatchTimeBuf = LocalTime.now() pause = false - disposable = Flowable.interval(0, 1, TimeUnit.MILLISECONDS) + disposableStopwatch = Flowable.interval(0, 1, TimeUnit.MILLISECONDS) .subscribeOn(Schedulers.computation()) .onBackpressureDrop() .observeOn(AndroidSchedulers.mainThread()) .subscribe( { val now = LocalTime.now() - stopwatchTime = stopwatchTime.plus(stopwatchTimeBuf.until(now, MILLIS), MILLIS) + stopwatchTime = + stopwatchTime.plus(stopwatchTimeBuf.until(now, MILLIS), MILLIS) stopwatchTimeBuf = now Log.d( LOG_TAG, @@ -150,8 +166,8 @@ class MainActivity : AppCompatActivity() { } stopwatchEndButton.setOnClickListener { - disposable?.dispose() - disposable = null + disposableStopwatch?.dispose() + disposableStopwatch = null if (pause) { Log.d(LOG_TAG, "clear timer") stopwatchStartButton.setText("START")