Commit d0276422 by likorn

Timing is now managed by TimerFragment

parent 18d8b0b0
package com.paktalin.quickmax package com.paktalin.quickmax
import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.content.Intent import android.content.Intent
import android.graphics.Color
import android.graphics.PorterDuff
import android.os.Bundle import android.os.Bundle
import android.os.CountDownTimer
import android.util.TypedValue
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.commit
import com.paktalin.quickmax.answers.Answer import com.paktalin.quickmax.answers.Answer
import com.paktalin.quickmax.answers.AnswerSet import com.paktalin.quickmax.answers.AnswerSet
import kotlinx.android.synthetic.main.activity_task.* import kotlinx.android.synthetic.main.activity_task.*
...@@ -17,19 +10,23 @@ import kotlinx.android.synthetic.main.activity_task.* ...@@ -17,19 +10,23 @@ import kotlinx.android.synthetic.main.activity_task.*
// TODO save state // TODO save state
class TaskActivity : AppCompatActivity() { class TaskActivity : AppCompatActivity() {
internal lateinit var answerSet: AnswerSet private lateinit var answerSet: AnswerSet
private var millisToSolve: Long = 4000 private var millisToSolve: Long = 4000
private var numDigits: Int = 3 private var numDigits: Int = 3
private lateinit var timer: CountDownTimer
private lateinit var colorAnimation: ValueAnimator
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_task) setContentView(R.layout.activity_task)
btn_back.setOnClickListener { startActivity(Intent(this@TaskActivity, MainActivity::class.java)) } btn_back.setOnClickListener {
startActivity(
Intent(
this@TaskActivity,
MainActivity::class.java
)
)
}
retrieveExtras() retrieveExtras()
initTimer()
startNewRound() startNewRound()
} }
...@@ -47,9 +44,9 @@ class TaskActivity : AppCompatActivity() { ...@@ -47,9 +44,9 @@ class TaskActivity : AppCompatActivity() {
numDigits, numDigits,
listOf(card_left_top, card_right_top, card_left_bottom, card_right_bottom) listOf(card_left_top, card_right_top, card_left_bottom, card_right_bottom)
) )
addTimerFragment(supportFragmentManager, millisToSolve)
setUpCards() setUpCards()
timer.start() removeButtonNextFragment(supportFragmentManager)
startColorAnimation()
} }
private fun retrieveExtras() { private fun retrieveExtras() {
...@@ -59,63 +56,28 @@ class TaskActivity : AppCompatActivity() { ...@@ -59,63 +56,28 @@ class TaskActivity : AppCompatActivity() {
private fun setUpCards() { private fun setUpCards() {
answerSet.forEach { answer -> answerSet.forEach { answer ->
answer.card.setOnCheckedChangeListener { _, isChecked -> if (isChecked) processAnswer(answer) } answer.card.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) processAnswer(answer)
}
answer.card.initial(this@TaskActivity, answer.value) answer.card.initial(this@TaskActivity, answer.value)
} }
} }
private fun processAnswer(answer: Answer) { private fun processAnswer(answer: Answer) {
timer.cancel()
colorAnimation.cancel()
setResponseText(answer)
answerSet.forEach { answer -> answer.card.disable()}
}
private fun setResponseText(answer: Answer) {
tv_response.setTextSize(TypedValue.COMPLEX_UNIT_SP, resources.getDimension(R.dimen.response_text_size))
if (answer.correct) { if (answer.correct) {
answer.card.markCorrect(this@TaskActivity) answer.card.markCorrect(this@TaskActivity)
tv_response.text = resources.getString(R.string.response_correct) (supportFragmentManager.findFragmentByTag("timer_fragment") as TimerFragment).cancelCorrect()
supportFragmentManager.commit(true) { addButtonNextFragment(supportFragmentManager, true)
add(R.id.main_layout, ButtonNextFragment().apply { arguments = Bundle().apply { putBoolean("correct", true) } })
}
} else { } else {
answer.card.markWrong(this@TaskActivity) answer.card.markWrong(this@TaskActivity)
tv_response.text = resources.getString(R.string.response_wrong) (supportFragmentManager.findFragmentByTag("timer_fragment") as TimerFragment).cancelWrong()
supportFragmentManager.commit(true) { addButtonNextFragment(supportFragmentManager, false)
add(R.id.main_layout, ButtonNextFragment().apply { arguments = Bundle().apply { putBoolean("correct", false) } })
}
} }
answerSet.forEach { answer -> answer.card.disable() }
} }
private fun startColorAnimation() { fun onTimeOver() {
val colorFrom = Color.TRANSPARENT addButtonNextFragment(supportFragmentManager, false)
val colorTo = color(this, R.color.transparent_red) answerSet.forEach { answer -> answer.card.disable() }
colorAnimation = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo)
.apply { duration = millisToSolve }
colorAnimation.addUpdateListener { animator ->
layout_gradient.background.setColorFilter(animator.animatedValue as Int,
PorterDuff.Mode.SRC_ATOP)
}
colorAnimation.start()
}
private fun initTimer() {
timer = object : CountDownTimer(millisToSolve, 1000) {
override fun onTick(millisUntilFinished: Long) {
tv_response.text = (millisUntilFinished/1000).toString()
}
override fun onFinish() {
tv_response.setTextSize(TypedValue.COMPLEX_UNIT_SP, resources.getDimension(R.dimen.response_text_size))
tv_response.text = resources.getString(R.string.time_is_over)
supportFragmentManager.commit(true) {
add(R.id.main_layout, ButtonNextFragment().apply { arguments = Bundle().apply { putBoolean("correct", false) } })
}
answerSet.forEach { answer -> answer.card.disable()}
}
}
} }
} }
package com.paktalin.quickmax
import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.graphics.Color
import android.graphics.PorterDuff
import android.os.Bundle
import android.os.CountDownTimer
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
class TimerFragment: Fragment() {
private lateinit var timer: CountDownTimer
private var millisToSolve: Long = 0
private val interval: Long = 1000
private lateinit var tvResponse: TextView
private lateinit var colorAnimation: ValueAnimator
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
millisToSolve = arguments!!.getLong("millis_to_solve")
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.gradient_timer, container, false)
tvResponse = view!!.findViewById(R.id.tv_response)
initTimer()
initColorAnimation()
return view
}
override fun onStart() {
super.onStart()
timer.start()
colorAnimation.start()
}
fun cancelCorrect() {
cancel()
tvResponse.text = resources.getString(R.string.response_correct)
}
fun cancelWrong() {
cancel()
tvResponse.text = resources.getString(R.string.response_wrong)
}
private fun cancel() {
timer.cancel()
colorAnimation.cancel()
tvResponse.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize(resources) )
}
private fun initTimer() {
timer = object : CountDownTimer(millisToSolve, interval) {
override fun onTick(millisUntilFinished: Long) {
tvResponse.text = (millisUntilFinished / interval).toString()
}
override fun onFinish() {
tvResponse.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize(resources) )
tvResponse.text = resources.getString(R.string.time_is_over)
(activity as TaskActivity).onTimeOver()
}
}
}
private fun initColorAnimation() {
val colorFrom = Color.TRANSPARENT
val colorTo = color(context!!, R.color.transparent_red)
colorAnimation = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo)
.apply { duration = millisToSolve }
colorAnimation.addUpdateListener { animator ->
view!!.background.setColorFilter(animator.animatedValue as Int, PorterDuff.Mode.SRC_ATOP)
}
}
}
\ No newline at end of file
package com.paktalin.quickmax package com.paktalin.quickmax
import android.content.Context import android.content.Context
import android.content.res.Resources
import android.os.Bundle
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.commit
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
fun getTextView(card: View): TextView { fun getTextView(card: View): TextView {
...@@ -14,3 +18,32 @@ fun getTextView(card: View): TextView { ...@@ -14,3 +18,32 @@ fun getTextView(card: View): TextView {
fun color(context: Context, id: Int): Int { fun color(context: Context, id: Int): Int {
return ContextCompat.getColor(context, id) return ContextCompat.getColor(context, id)
} }
fun textSize(resources: Resources): Float {
val screenDensity = resources.displayMetrics.density
return resources.getDimension(R.dimen.response_text_size) / screenDensity
}
fun addTimerFragment(supportFragmentManager: FragmentManager, millisToSolve: Long) {
val timerFragment = TimerFragment().apply {
arguments = Bundle().apply { putLong("millis_to_solve", millisToSolve) }
}
supportFragmentManager.commit(true) {
replace(R.id.fragment_timer, timerFragment, "timer_fragment")
}
}
fun addButtonNextFragment(supportFragmentManager: FragmentManager, correct: Boolean) {
val fragmentBtnNext = ButtonNextFragment().apply {
arguments = Bundle().apply { putBoolean("correct", correct) }
}
supportFragmentManager.commit(true) {
add(R.id.main_layout, fragmentBtnNext, "btn_next_fragment")
}
}
fun removeButtonNextFragment(supportFragmentManager: FragmentManager) {
supportFragmentManager.findFragmentByTag("btn_next_fragment")?.let {fragment ->
supportFragmentManager.commit(true) { remove(fragment) }
}
}
\ No newline at end of file
...@@ -46,9 +46,11 @@ ...@@ -46,9 +46,11 @@
android:text="@string/response_correct" android:text="@string/response_correct"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:textSize="60sp" android:textSize="60sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/cv_task" app:layout_constraintEnd_toEndOf="@+id/cv_task"
app:layout_constraintStart_toStartOf="@+id/cv_task" app:layout_constraintStart_toStartOf="@+id/cv_task"
app:layout_constraintTop_toTopOf="@+id/layout_answers" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.25"
app:layout_constraintVertical_chainStyle="spread" /> app:layout_constraintVertical_chainStyle="spread" />
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
......
...@@ -8,16 +8,15 @@ ...@@ -8,16 +8,15 @@
android:background="#DADADA" android:background="#DADADA"
tools:context="com.paktalin.quickmax.TaskActivity"> tools:context="com.paktalin.quickmax.TaskActivity">
<View <FrameLayout
android:id="@+id/layout_gradient" android:id="@+id/fragment_timer"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginBottom="32dp"
android:background="@drawable/gradient"
app:layout_constraintBottom_toBottomOf="@+id/cv_task" app:layout_constraintBottom_toBottomOf="@+id/cv_task"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/> app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="32dp" />
<ImageButton <ImageButton
android:id="@+id/btn_back" android:id="@+id/btn_back"
...@@ -31,20 +30,6 @@ ...@@ -31,20 +30,6 @@
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_back" /> app:srcCompat="@drawable/ic_back" />
<TextView
android:id="@+id/tv_response"
style="@style/TextAppearance.MaterialComponents.Headline4"
android:layout_width="0dp"
android:layout_height="0dp"
android:elevation="2dp"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="60sp"
app:layout_constraintBottom_toTopOf="@+id/cv_task"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:id="@+id/cv_task" android:id="@+id/cv_task"
android:layout_width="0dp" android:layout_width="0dp"
......
<?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"
android:background="@drawable/gradient"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_response"
style="@style/TextAppearance.MaterialComponents.Headline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="2dp"
android:gravity="center"
android:text="@string/response_correct"
android:textColor="@android:color/white"
android:textSize="60sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.4" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<dimen name="response_text_size">14sp</dimen> <dimen name="response_text_size">40sp</dimen>
</resources> </resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment