154 lines
6.0 KiB
Kotlin
154 lines
6.0 KiB
Kotlin
package com.dano.test1
|
||
|
||
import android.view.View
|
||
import android.widget.*
|
||
import android.text.Html
|
||
import kotlinx.coroutines.*
|
||
import android.util.TypedValue
|
||
import android.widget.TextView
|
||
import androidx.core.widget.TextViewCompat
|
||
import com.google.android.material.button.MaterialButton
|
||
|
||
/*
|
||
Zweck:
|
||
- Steuert die letzte Seite eines Fragebogens.
|
||
- Zeigt Abschlusstexte an, speichert alle gesammelten Antworten in die lokale DB und beendet anschließend den Fragebogen und kehrt zur übergeordneten Ansicht zurück.
|
||
|
||
Beim Klick auf „Speichern“:
|
||
- Ladezustand anzeigen (ProgressBar), Buttons deaktivieren.
|
||
- Antworten asynchron in Room-DB persistieren (über `saveAnswersToDatabase`).
|
||
- Punktsumme ermitteln und in `GlobalValues.INTEGRATION_INDEX` schreiben.
|
||
- `client_code` (falls vorhanden) als `GlobalValues.LAST_CLIENT_CODE` merken.
|
||
- Mindestens 2 Sekunden „Loading“-Dauer sicherstellen (ruhiges UX).
|
||
- Zurück auf den Main-Thread wechseln, UI entsperren und Fragebogen schließen.
|
||
|
||
*/
|
||
|
||
class HandlerLastPage(
|
||
private val answers: Map<String, Any>,
|
||
private val languageID: String,
|
||
private val goToNextQuestion: () -> Unit,
|
||
private val goToPreviousQuestion: () -> Unit,
|
||
private val saveAnswersToDatabase: suspend (Map<String, Any>) -> Unit
|
||
) : QuestionHandler {
|
||
|
||
private lateinit var currentQuestion: QuestionItem.LastPage
|
||
private lateinit var layout: View
|
||
private val minLoadingTimeMs = 2000L
|
||
|
||
override fun bind(layout: View, question: QuestionItem) {
|
||
this.layout = layout
|
||
currentQuestion = question as QuestionItem.LastPage
|
||
|
||
val titleTv = layout.findViewById<TextView>(R.id.textView)
|
||
val questionTv = layout.findViewById<TextView>(R.id.question)
|
||
val prevBtn = layout.findViewById<MaterialButton>(R.id.Qprev)
|
||
val finishBtn = layout.findViewById<MaterialButton>(R.id.Qfinish)
|
||
|
||
// Texte setzen
|
||
titleTv.text = LanguageManager.getText(languageID, currentQuestion.textKey)
|
||
questionTv.text = Html.fromHtml(
|
||
LanguageManager.getText(languageID, currentQuestion.question),
|
||
Html.FROM_HTML_MODE_LEGACY
|
||
)
|
||
|
||
// Finish-Button: Text + responsive Schrift
|
||
finishBtn.text = LanguageManager.getText(languageID, "save")
|
||
finishBtn.isAllCaps = false
|
||
applyResponsiveTextSizing(finishBtn)
|
||
|
||
// Überschriften responsiv skalieren (wie zuvor)
|
||
setTextSizePercentOfScreenHeight(titleTv, 0.03f)
|
||
setTextSizePercentOfScreenHeight(questionTv, 0.03f)
|
||
|
||
// Buttons
|
||
prevBtn.setOnClickListener { goToPreviousQuestion() }
|
||
|
||
finishBtn.setOnClickListener {
|
||
showLoading(true)
|
||
|
||
CoroutineScope(Dispatchers.IO).launch {
|
||
val startTime = System.currentTimeMillis()
|
||
|
||
// Antworten speichern
|
||
saveAnswersToDatabase(answers)
|
||
|
||
// Punkte summieren
|
||
GlobalValues.INTEGRATION_INDEX = sumPoints()
|
||
|
||
// Client-Code merken (für Auto-Laden im Opening Screen)
|
||
val clientCode = answers["client_code"] as? String
|
||
if (clientCode != null) {
|
||
GlobalValues.LAST_CLIENT_CODE = clientCode
|
||
GlobalValues.LOADED_CLIENT_CODE = clientCode // <— zusätzlich setzen
|
||
}
|
||
|
||
// min. Ladezeit einhalten (ruhiges UX)
|
||
val elapsedTime = System.currentTimeMillis() - startTime
|
||
if (elapsedTime < minLoadingTimeMs) delay(minLoadingTimeMs - elapsedTime)
|
||
|
||
withContext(Dispatchers.Main) {
|
||
showLoading(false)
|
||
val activity = layout.context as? MainActivity
|
||
// Zurück zum Opening Screen – der lädt dann automatisch (siehe Änderung 2)
|
||
activity?.finishQuestionnaire() ?: goToNextQuestion()
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
override fun validate(): Boolean = true
|
||
override fun saveAnswer() {}
|
||
|
||
private fun applyResponsiveTextSizing(btn: MaterialButton) {
|
||
// Max-/Min-Sp anhand der Bildschirmhöhe (in sp) berechnen
|
||
val dm = btn.resources.displayMetrics
|
||
val maxSp = (dm.heightPixels * 0.028f) / dm.scaledDensity // ~2.8% der Höhe
|
||
val minSp = (dm.heightPixels * 0.018f) / dm.scaledDensity // ~1.8% der Höhe
|
||
|
||
// AutoSize aktivieren (schrumpft/expandiert den Text innerhalb des Buttons)
|
||
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(
|
||
btn,
|
||
minSp.toInt(),
|
||
maxSp.toInt(),
|
||
1,
|
||
TypedValue.COMPLEX_UNIT_SP
|
||
)
|
||
btn.setSingleLine(true)
|
||
btn.maxLines = 1
|
||
btn.isAllCaps = false
|
||
|
||
// Padding nach Layout proportional zur Button-Höhe setzen (wirkt auf Lesbarkeit)
|
||
btn.post {
|
||
val padH = (btn.height * 0.18f).toInt()
|
||
val padV = (btn.height * 0.12f).toInt()
|
||
btn.setPadding(padH, padV, padH, padV)
|
||
}
|
||
}
|
||
// ----------------------------------------------------------------
|
||
|
||
// Helper: Textgröße prozentual zur Bildschirmhöhe setzen (in sp)
|
||
private fun setTextSizePercentOfScreenHeight(view: TextView, percentOfHeight: Float) {
|
||
val dm = (view.context ?: layout.context).resources.displayMetrics
|
||
val sp = (dm.heightPixels * percentOfHeight) / dm.scaledDensity
|
||
TextViewCompat.setAutoSizeTextTypeWithDefaults(view, TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE)
|
||
view.setTextSize(TypedValue.COMPLEX_UNIT_SP, sp)
|
||
}
|
||
|
||
private fun sumPoints(): Int =
|
||
answers.filterKeys { it.endsWith("_points") }
|
||
.values.mapNotNull { it as? Int }
|
||
.sum()
|
||
|
||
private fun showLoading(show: Boolean) {
|
||
val progressBar = layout.findViewById<ProgressBar>(R.id.progressBar)
|
||
val finishButton = layout.findViewById<Button>(R.id.Qfinish)
|
||
val prevButton = layout.findViewById<Button>(R.id.Qprev)
|
||
|
||
progressBar?.visibility = if (show) View.VISIBLE else View.GONE
|
||
finishButton?.isEnabled = !show
|
||
prevButton?.isEnabled = !show
|
||
}
|
||
}
|