fixed online connection error and class scale question bug
This commit is contained in:
1
.idea/misc.xml
generated
1
.idea/misc.xml
generated
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||
|
||||
@ -9,11 +9,10 @@ import androidx.core.widget.TextViewCompat
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
/*
|
||||
|
||||
Zweck:
|
||||
- Stellt eine „Glas-Skala“-Frage dar, bei der pro Symptom (Zeile) genau eine von fünf Antwortstufen gewählt wird: never / little / moderate / much / extreme.
|
||||
- Die Stufen werden sowohl als RadioButtons als auch über eine feste Icon-Leiste visualisiert.
|
||||
|
||||
- „Glas-Skala“-Frage: pro Symptom (Zeile) genau eine von fünf Stufen.
|
||||
- Stufen als RadioButtons (clickbar) + Icon-Header.
|
||||
- FIX: Pro Zeile wird Single-Select erzwungen (auch im Bearbeiten-Modus / Restore).
|
||||
*/
|
||||
|
||||
class HandlerGlassScaleQuestion(
|
||||
@ -54,6 +53,9 @@ class HandlerGlassScaleQuestion(
|
||||
"extreme_glass" to R.drawable.ic_glass_4
|
||||
)
|
||||
|
||||
// Damit wir beim programmatic-check keine Endlosschleifen triggern
|
||||
private var suppressRowListener: Boolean = false
|
||||
|
||||
override fun bind(layout: View, question: QuestionItem) {
|
||||
if (question !is QuestionItem.GlassScaleQuestion) return
|
||||
this.layout = layout
|
||||
@ -65,15 +67,16 @@ class HandlerGlassScaleQuestion(
|
||||
titleTv.text = question.textKey?.let { LanguageManager.getText(languageID, it) } ?: ""
|
||||
questionTv.text = question.question?.let { LanguageManager.getText(languageID, it) } ?: ""
|
||||
|
||||
setTextSizePercentOfScreenHeight(titleTv, 0.03f)
|
||||
setTextSizePercentOfScreenHeight(titleTv, 0.03f)
|
||||
setTextSizePercentOfScreenHeight(questionTv, 0.03f)
|
||||
|
||||
// feste Icon-Leiste
|
||||
// Header Icons
|
||||
val header = layout.findViewById<LinearLayout>(R.id.glass_header)
|
||||
header.removeAllViews()
|
||||
header.addView(Space(context).apply {
|
||||
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 4f)
|
||||
})
|
||||
|
||||
val iconSizePx = (context.resources.displayMetrics.density * 36).toInt()
|
||||
scaleLabels.forEach { labelKey ->
|
||||
val cell = FrameLayout(context).apply {
|
||||
@ -88,13 +91,12 @@ class HandlerGlassScaleQuestion(
|
||||
cell.addView(img)
|
||||
header.addView(cell)
|
||||
}
|
||||
//
|
||||
|
||||
val tableLayout = layout.findViewById<TableLayout>(R.id.glass_table)
|
||||
tableLayout.removeAllViews()
|
||||
addSymptomRows(tableLayout)
|
||||
|
||||
// ggf. Antworten aus DB wiederherstellen
|
||||
// Restore aus DB (nur wenn noch nicht im answers)
|
||||
val anySymptomNeedsRestore = question.symptoms.any { !answers.containsKey(it) }
|
||||
if (anySymptomNeedsRestore) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
@ -104,21 +106,14 @@ class HandlerGlassScaleQuestion(
|
||||
val answerMap = allAnswersForClient.associateBy({ it.questionId }, { it.answerValue })
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
val table = tableLayout
|
||||
for ((index, symptomKey) in question.symptoms.withIndex()) {
|
||||
val answerMapKey = "$questionnaireMeta-$symptomKey"
|
||||
val dbAnswer = answerMap[answerMapKey]?.takeIf { it.isNotBlank() }?.trim()
|
||||
if (!answers.containsKey(symptomKey) && !dbAnswer.isNullOrBlank()) {
|
||||
if (index < table.childCount) {
|
||||
val row = table.getChildAt(index) as? TableRow ?: continue
|
||||
if (index < tableLayout.childCount) {
|
||||
val row = tableLayout.getChildAt(index) as? TableRow ?: continue
|
||||
val radioGroup = row.getChildAt(1) as? RadioGroup ?: continue
|
||||
for (i in 0 until radioGroup.childCount) {
|
||||
val rb = getRadioFromChild(radioGroup.getChildAt(i)) ?: continue
|
||||
if ((rb.tag as? String)?.trim() == dbAnswer) {
|
||||
rb.isChecked = true
|
||||
break
|
||||
}
|
||||
}
|
||||
setSingleSelection(radioGroup, dbAnswer) // <-- FIXED restore
|
||||
answers[symptomKey] = dbAnswer
|
||||
points.add(pointsMap[dbAnswer] ?: 0)
|
||||
}
|
||||
@ -165,30 +160,75 @@ class HandlerGlassScaleQuestion(
|
||||
setPadding(0, 0, 0, 0)
|
||||
}
|
||||
|
||||
// Build buttons
|
||||
scaleLabels.forEach { labelKey ->
|
||||
val cell = FrameLayout(context).apply {
|
||||
layoutParams = RadioGroup.LayoutParams(0, RadioGroup.LayoutParams.WRAP_CONTENT, 1f)
|
||||
}
|
||||
|
||||
val rb = RadioButton(context).apply {
|
||||
tag = labelKey
|
||||
id = View.generateViewId()
|
||||
isChecked = savedLabel == labelKey
|
||||
isChecked = false
|
||||
setPadding(0, 0, 0, 0)
|
||||
}
|
||||
|
||||
rb.layoutParams = FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
Gravity.CENTER
|
||||
)
|
||||
|
||||
// <<< FIX: erzwinge pro Zeile genau eine Auswahl
|
||||
rb.setOnCheckedChangeListener { buttonView, isChecked ->
|
||||
if (suppressRowListener) return@setOnCheckedChangeListener
|
||||
if (!isChecked) return@setOnCheckedChangeListener
|
||||
|
||||
val selectedLabel = buttonView.tag as? String ?: return@setOnCheckedChangeListener
|
||||
// wenn einer checked -> alle anderen in dieser Row unchecken
|
||||
suppressRowListener = true
|
||||
try {
|
||||
for (i in 0 until radioGroup.childCount) {
|
||||
val other = getRadioFromChild(radioGroup.getChildAt(i)) ?: continue
|
||||
if (other != buttonView) other.isChecked = false
|
||||
}
|
||||
} finally {
|
||||
suppressRowListener = false
|
||||
}
|
||||
|
||||
// Optional (wenn du willst): sofort im answers setzen (Edit-Mode fühlt sich dann "direkt" an)
|
||||
answers[symptomKey] = selectedLabel
|
||||
}
|
||||
|
||||
cell.addView(rb)
|
||||
radioGroup.addView(cell)
|
||||
}
|
||||
|
||||
// Restore aus answers (falls vorhanden)
|
||||
if (!savedLabel.isNullOrBlank()) {
|
||||
setSingleSelection(radioGroup, savedLabel)
|
||||
}
|
||||
|
||||
row.addView(radioGroup)
|
||||
table.addView(row)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt in diesem Row-RadioGroup genau einen Wert aktiv und alle anderen aus.
|
||||
*/
|
||||
private fun setSingleSelection(radioGroup: RadioGroup, labelKey: String) {
|
||||
suppressRowListener = true
|
||||
try {
|
||||
for (i in 0 until radioGroup.childCount) {
|
||||
val rb = getRadioFromChild(radioGroup.getChildAt(i)) ?: continue
|
||||
val tag = (rb.tag as? String)?.trim()
|
||||
rb.isChecked = (tag == labelKey.trim())
|
||||
}
|
||||
} finally {
|
||||
suppressRowListener = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun validate(): Boolean {
|
||||
val table = layout.findViewById<TableLayout>(R.id.glass_table)
|
||||
@ -217,6 +257,7 @@ class HandlerGlassScaleQuestion(
|
||||
val row = table.getChildAt(i) as TableRow
|
||||
val symptomKey = question.symptoms[i]
|
||||
val radioGroup = row.getChildAt(1) as RadioGroup
|
||||
|
||||
for (j in 0 until radioGroup.childCount) {
|
||||
val rb = getRadioFromChild(radioGroup.getChildAt(j)) ?: continue
|
||||
if (rb.isChecked) {
|
||||
|
||||
Reference in New Issue
Block a user