created shared functions in ViewUtils.kt
This commit is contained in:
@ -2,8 +2,6 @@ package com.dano.test1.questionnaire.handlers
|
|||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import android.util.TypedValue
|
|
||||||
import androidx.core.widget.TextViewCompat
|
|
||||||
import com.dano.test1.questionnaire.GlobalValues
|
import com.dano.test1.questionnaire.GlobalValues
|
||||||
import com.dano.test1.LanguageManager
|
import com.dano.test1.LanguageManager
|
||||||
import com.dano.test1.MyApp
|
import com.dano.test1.MyApp
|
||||||
@ -11,6 +9,7 @@ import com.dano.test1.questionnaire.QuestionHandler
|
|||||||
import com.dano.test1.questionnaire.QuestionItem
|
import com.dano.test1.questionnaire.QuestionItem
|
||||||
import com.dano.test1.R
|
import com.dano.test1.R
|
||||||
import com.dano.test1.network.TokenStore
|
import com.dano.test1.network.TokenStore
|
||||||
|
import com.dano.test1.utils.ViewUtils
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -45,10 +44,10 @@ class HandlerClientCoachCode(
|
|||||||
|
|
||||||
questionTextView.text = question.question?.let { LanguageManager.getText(languageID, it) } ?: ""
|
questionTextView.text = question.question?.let { LanguageManager.getText(languageID, it) } ?: ""
|
||||||
|
|
||||||
setTextSizePercentOfScreenHeight(titleTextView, 0.03f)
|
ViewUtils.setTextSizePercentOfScreenHeight(titleTextView, 0.03f)
|
||||||
setTextSizePercentOfScreenHeight(questionTextView, 0.03f)
|
ViewUtils.setTextSizePercentOfScreenHeight(questionTextView, 0.03f)
|
||||||
setTextSizePercentOfScreenHeight(clientCodeField, 0.025f)
|
ViewUtils.setTextSizePercentOfScreenHeight(clientCodeField, 0.025f)
|
||||||
setTextSizePercentOfScreenHeight(coachCodeField, 0.025f)
|
ViewUtils.setTextSizePercentOfScreenHeight(coachCodeField, 0.025f)
|
||||||
|
|
||||||
// Client-Code: nur verwenden, wenn bereits geladen
|
// Client-Code: nur verwenden, wenn bereits geladen
|
||||||
val loadedClientCode = GlobalValues.LOADED_CLIENT_CODE
|
val loadedClientCode = GlobalValues.LOADED_CLIENT_CODE
|
||||||
@ -64,7 +63,7 @@ class HandlerClientCoachCode(
|
|||||||
val coachFromLogin = TokenStore.getUsername(layout.context)
|
val coachFromLogin = TokenStore.getUsername(layout.context)
|
||||||
if (!coachFromLogin.isNullOrBlank()) {
|
if (!coachFromLogin.isNullOrBlank()) {
|
||||||
coachCodeField.setText(coachFromLogin)
|
coachCodeField.setText(coachFromLogin)
|
||||||
lockCoachField(coachCodeField) // optisch & technisch gesperrt
|
ViewUtils.lockEditField(coachCodeField) // optisch & technisch gesperrt
|
||||||
} else {
|
} else {
|
||||||
// Falls (theoretisch) kein Login-Username vorhanden ist, verhalten wie bisher
|
// Falls (theoretisch) kein Login-Username vorhanden ist, verhalten wie bisher
|
||||||
coachCodeField.setText(answers["coach_code"] as? String ?: "")
|
coachCodeField.setText(answers["coach_code"] as? String ?: "")
|
||||||
@ -79,13 +78,6 @@ class HandlerClientCoachCode(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setTextSizePercentOfScreenHeight(view: TextView, percentOfHeight: Float) {
|
|
||||||
val dm = layout.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 onNextClicked(clientCodeField: EditText, coachCodeField: EditText) {
|
private fun onNextClicked(clientCodeField: EditText, coachCodeField: EditText) {
|
||||||
val loadedClientCode = GlobalValues.LOADED_CLIENT_CODE
|
val loadedClientCode = GlobalValues.LOADED_CLIENT_CODE
|
||||||
|
|
||||||
@ -150,19 +142,4 @@ class HandlerClientCoachCode(
|
|||||||
// Not used
|
// Not used
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lockCoachField(field: EditText) {
|
|
||||||
field.isFocusable = false
|
|
||||||
field.isFocusableInTouchMode = false
|
|
||||||
field.isCursorVisible = false
|
|
||||||
field.keyListener = null
|
|
||||||
field.isLongClickable = false
|
|
||||||
field.isClickable = false
|
|
||||||
field.setBackgroundResource(R.drawable.bg_field_locked)
|
|
||||||
field.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_lock_24, 0)
|
|
||||||
field.compoundDrawablePadding = dp(8)
|
|
||||||
field.alpha = 0.95f
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun dp(v: Int): Int =
|
|
||||||
(v * layout.resources.displayMetrics.density).toInt()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,15 +2,10 @@ package com.dano.test1.questionnaire.handlers
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.Gravity
|
|
||||||
import androidx.core.widget.TextViewCompat
|
|
||||||
import android.widget.AbsListView
|
|
||||||
import com.dano.test1.questionnaire.GlobalValues
|
import com.dano.test1.questionnaire.GlobalValues
|
||||||
import com.dano.test1.LanguageManager
|
import com.dano.test1.LanguageManager
|
||||||
import com.dano.test1.questionnaire.MAX_VALUE_YEAR
|
import com.dano.test1.questionnaire.MAX_VALUE_YEAR
|
||||||
@ -20,6 +15,7 @@ import com.dano.test1.MyApp
|
|||||||
import com.dano.test1.questionnaire.QuestionHandler
|
import com.dano.test1.questionnaire.QuestionHandler
|
||||||
import com.dano.test1.questionnaire.QuestionItem
|
import com.dano.test1.questionnaire.QuestionItem
|
||||||
import com.dano.test1.R
|
import com.dano.test1.R
|
||||||
|
import com.dano.test1.utils.ViewUtils
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Zweck:
|
Zweck:
|
||||||
@ -62,12 +58,11 @@ class HandlerDateSpinner(
|
|||||||
textView.text = question.textKey?.let { LanguageManager.getText(languageID, it) } ?: ""
|
textView.text = question.textKey?.let { LanguageManager.getText(languageID, it) } ?: ""
|
||||||
|
|
||||||
// Schriftgrößen pro Bildschirmhöhe
|
// Schriftgrößen pro Bildschirmhöhe
|
||||||
setTextSizePercentOfScreenHeight(textView, 0.03f) // oben
|
ViewUtils.setTextSizePercentOfScreenHeight(textView, 0.03f)
|
||||||
setTextSizePercentOfScreenHeight(questionTextView, 0.03f) // frage
|
ViewUtils.setTextSizePercentOfScreenHeight(questionTextView, 0.03f)
|
||||||
setTextSizePercentOfScreenHeight(labelDay, 0.025f)
|
ViewUtils.setTextSizePercentOfScreenHeight(labelDay, 0.025f)
|
||||||
setTextSizePercentOfScreenHeight(labelMonth, 0.025f)
|
ViewUtils.setTextSizePercentOfScreenHeight(labelMonth, 0.025f)
|
||||||
setTextSizePercentOfScreenHeight(labelYear, 0.025f)
|
ViewUtils.setTextSizePercentOfScreenHeight(labelYear, 0.025f)
|
||||||
//
|
|
||||||
|
|
||||||
// gespeicherte Antwort (YYYY-MM-DD) lesen
|
// gespeicherte Antwort (YYYY-MM-DD) lesen
|
||||||
val (savedYear, savedMonthIndex, savedDay) = question.question?.let {
|
val (savedYear, savedMonthIndex, savedDay) = question.question?.let {
|
||||||
@ -85,9 +80,9 @@ class HandlerDateSpinner(
|
|||||||
val defaultYear = savedYear ?: today.get(Calendar.YEAR)
|
val defaultYear = savedYear ?: today.get(Calendar.YEAR)
|
||||||
|
|
||||||
// Spinner responsiv aufsetzen (Schrift + Zeilenhöhe ohne Abschneiden)
|
// Spinner responsiv aufsetzen (Schrift + Zeilenhöhe ohne Abschneiden)
|
||||||
setupSpinner(spinnerDay, days, defaultDay)
|
ViewUtils.setupResponsiveSpinner(context, spinnerDay, days, defaultDay)
|
||||||
setupSpinner(spinnerMonth, months, defaultMonth)
|
ViewUtils.setupResponsiveSpinner(context, spinnerMonth, months, defaultMonth)
|
||||||
setupSpinner(spinnerYear, years, defaultYear)
|
ViewUtils.setupResponsiveSpinner(context, spinnerYear, years, defaultYear)
|
||||||
|
|
||||||
// DB-Abfrage, falls noch nicht im answers-Map
|
// DB-Abfrage, falls noch nicht im answers-Map
|
||||||
val answerMapKey = question.question ?: (question.id ?: "")
|
val answerMapKey = question.question ?: (question.id ?: "")
|
||||||
@ -217,71 +212,4 @@ class HandlerDateSpinner(
|
|||||||
return sdf.parse(dateString)
|
return sdf.parse(dateString)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Textgröße prozentual zur Bildschirmhöhe (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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spinner-Adapter: Schrift & Zeilenhöhe dynamisch, kein Abschneiden
|
|
||||||
private fun <T> setupSpinner(spinner: Spinner, items: List<T>, defaultSelection: T?) {
|
|
||||||
val dm = context.resources.displayMetrics
|
|
||||||
|
|
||||||
fun spFromScreenHeight(percent: Float): Float =
|
|
||||||
(dm.heightPixels * percent) / dm.scaledDensity
|
|
||||||
fun pxFromSp(sp: Float): Int = (sp * dm.scaledDensity).toInt()
|
|
||||||
|
|
||||||
val textSp = spFromScreenHeight(0.0275f) // ~2.75% der Bildschirmhöhe
|
|
||||||
val textPx = pxFromSp(textSp)
|
|
||||||
val vPadPx = (textPx * 0.50f).toInt() // vertikales Padding
|
|
||||||
val rowHeight = (textPx * 2.20f + 2 * vPadPx).toInt() // feste Zeilenhöhe
|
|
||||||
|
|
||||||
val adapter = object : ArrayAdapter<T>(context, android.R.layout.simple_spinner_item, items) {
|
|
||||||
private fun styleRow(tv: TextView, forceHeight: Boolean) {
|
|
||||||
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSp)
|
|
||||||
tv.includeFontPadding = true
|
|
||||||
tv.setLineSpacing(0f, 1.2f)
|
|
||||||
tv.gravity = (tv.gravity and Gravity.HORIZONTAL_GRAVITY_MASK) or Gravity.CENTER_VERTICAL
|
|
||||||
tv.setPadding(tv.paddingLeft, vPadPx, tv.paddingRight, vPadPx)
|
|
||||||
tv.minHeight = rowHeight
|
|
||||||
tv.isSingleLine = true
|
|
||||||
if (forceHeight) {
|
|
||||||
val lp = tv.layoutParams
|
|
||||||
if (lp == null || lp.height <= 0) {
|
|
||||||
tv.layoutParams = AbsListView.LayoutParams(
|
|
||||||
AbsListView.LayoutParams.MATCH_PARENT, rowHeight
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
lp.height = rowHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
|
||||||
val v = super.getView(position, convertView, parent) as TextView
|
|
||||||
styleRow(v, forceHeight = false)
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
|
|
||||||
val v = super.getDropDownView(position, convertView, parent) as TextView
|
|
||||||
styleRow(v, forceHeight = true)
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
|
||||||
spinner.adapter = adapter
|
|
||||||
|
|
||||||
spinner.setPadding(spinner.paddingLeft, vPadPx, spinner.paddingRight, vPadPx)
|
|
||||||
spinner.minimumHeight = rowHeight
|
|
||||||
spinner.requestLayout()
|
|
||||||
|
|
||||||
defaultSelection?.let {
|
|
||||||
val index = items.indexOf(it)
|
|
||||||
if (index >= 0) spinner.setSelection(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,16 @@
|
|||||||
package com.dano.test1.questionnaire.handlers
|
package com.dano.test1.questionnaire.handlers
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import androidx.core.widget.TextViewCompat
|
|
||||||
import com.dano.test1.questionnaire.GlobalValues
|
import com.dano.test1.questionnaire.GlobalValues
|
||||||
import com.dano.test1.LanguageManager
|
import com.dano.test1.LanguageManager
|
||||||
import com.dano.test1.MyApp
|
import com.dano.test1.MyApp
|
||||||
import com.dano.test1.questionnaire.QuestionHandler
|
import com.dano.test1.questionnaire.QuestionHandler
|
||||||
import com.dano.test1.questionnaire.QuestionItem
|
import com.dano.test1.questionnaire.QuestionItem
|
||||||
import com.dano.test1.R
|
import com.dano.test1.R
|
||||||
|
import com.dano.test1.utils.ViewUtils
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -73,8 +72,8 @@ class HandlerGlassScaleQuestion(
|
|||||||
titleTv.text = question.textKey?.let { LanguageManager.getText(languageID, it) } ?: ""
|
titleTv.text = question.textKey?.let { LanguageManager.getText(languageID, it) } ?: ""
|
||||||
questionTv.text = question.question?.let { LanguageManager.getText(languageID, it) } ?: ""
|
questionTv.text = question.question?.let { LanguageManager.getText(languageID, it) } ?: ""
|
||||||
|
|
||||||
setTextSizePercentOfScreenHeight(titleTv, 0.03f)
|
ViewUtils.setTextSizePercentOfScreenHeight(titleTv, 0.03f)
|
||||||
setTextSizePercentOfScreenHeight(questionTv, 0.03f)
|
ViewUtils.setTextSizePercentOfScreenHeight(questionTv, 0.03f)
|
||||||
|
|
||||||
// Header Icons
|
// Header Icons
|
||||||
val header = layout.findViewById<LinearLayout>(R.id.glass_header)
|
val header = layout.findViewById<LinearLayout>(R.id.glass_header)
|
||||||
@ -156,7 +155,7 @@ class HandlerGlassScaleQuestion(
|
|||||||
text = LanguageManager.getText(languageID, symptomKey)
|
text = LanguageManager.getText(languageID, symptomKey)
|
||||||
layoutParams = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT, 4f)
|
layoutParams = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT, 4f)
|
||||||
setPadding(4, 16, 4, 16)
|
setPadding(4, 16, 4, 16)
|
||||||
setTextSizePercentOfScreenHeight(this, 0.022f)
|
ViewUtils.setTextSizePercentOfScreenHeight(this, 0.022f)
|
||||||
}
|
}
|
||||||
row.addView(symptomText)
|
row.addView(symptomText)
|
||||||
|
|
||||||
@ -283,10 +282,4 @@ class HandlerGlassScaleQuestion(
|
|||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,18 +1,18 @@
|
|||||||
package com.dano.test1.questionnaire.handlers
|
package com.dano.test1.questionnaire.handlers
|
||||||
|
|
||||||
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import android.text.Html
|
import android.text.Html
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import android.util.TypedValue
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.widget.TextViewCompat
|
import androidx.core.widget.TextViewCompat
|
||||||
|
import kotlinx.coroutines.*
|
||||||
import com.dano.test1.questionnaire.GlobalValues
|
import com.dano.test1.questionnaire.GlobalValues
|
||||||
import com.dano.test1.LanguageManager
|
import com.dano.test1.LanguageManager
|
||||||
import com.dano.test1.MainActivity
|
import com.dano.test1.MainActivity
|
||||||
import com.dano.test1.questionnaire.QuestionHandler
|
import com.dano.test1.questionnaire.QuestionHandler
|
||||||
import com.dano.test1.questionnaire.QuestionItem
|
import com.dano.test1.questionnaire.QuestionItem
|
||||||
import com.dano.test1.R
|
import com.dano.test1.R
|
||||||
|
import com.dano.test1.utils.ViewUtils
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -64,8 +64,8 @@ class HandlerLastPage(
|
|||||||
applyResponsiveTextSizing(finishBtn)
|
applyResponsiveTextSizing(finishBtn)
|
||||||
|
|
||||||
// Überschriften responsiv skalieren (wie zuvor)
|
// Überschriften responsiv skalieren (wie zuvor)
|
||||||
setTextSizePercentOfScreenHeight(titleTv, 0.03f)
|
ViewUtils.setTextSizePercentOfScreenHeight(titleTv, 0.03f)
|
||||||
setTextSizePercentOfScreenHeight(questionTv, 0.03f)
|
ViewUtils.setTextSizePercentOfScreenHeight(questionTv, 0.03f)
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
prevBtn.setOnClickListener { goToPreviousQuestion() }
|
prevBtn.setOnClickListener { goToPreviousQuestion() }
|
||||||
@ -134,14 +134,6 @@ class HandlerLastPage(
|
|||||||
}
|
}
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
// 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 =
|
private fun sumPoints(): Int =
|
||||||
answers.filterKeys { it.endsWith("_points") }
|
answers.filterKeys { it.endsWith("_points") }
|
||||||
.values.mapNotNull { it as? Int }
|
.values.mapNotNull { it as? Int }
|
||||||
|
|||||||
@ -1,17 +1,18 @@
|
|||||||
package com.dano.test1.questionnaire.handlers
|
package com.dano.test1.questionnaire.handlers
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import android.util.TypedValue
|
|
||||||
import androidx.core.widget.TextViewCompat
|
import androidx.core.widget.TextViewCompat
|
||||||
|
import kotlinx.coroutines.*
|
||||||
import com.dano.test1.questionnaire.GlobalValues
|
import com.dano.test1.questionnaire.GlobalValues
|
||||||
import com.dano.test1.LanguageManager
|
import com.dano.test1.LanguageManager
|
||||||
import com.dano.test1.MyApp
|
import com.dano.test1.MyApp
|
||||||
import com.dano.test1.questionnaire.QuestionHandler
|
import com.dano.test1.questionnaire.QuestionHandler
|
||||||
import com.dano.test1.questionnaire.QuestionItem
|
import com.dano.test1.questionnaire.QuestionItem
|
||||||
import com.dano.test1.R
|
import com.dano.test1.R
|
||||||
|
import com.dano.test1.utils.ViewUtils
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Zweck:
|
Zweck:
|
||||||
@ -44,8 +45,8 @@ class HandlerMultiCheckboxQuestion(
|
|||||||
questionTitle.text = this.question.question?.let { LanguageManager.getText(languageID, it) } ?: ""
|
questionTitle.text = this.question.question?.let { LanguageManager.getText(languageID, it) } ?: ""
|
||||||
|
|
||||||
// Textgrößen pro Bildschirmhöhe (wie bei deinen anderen Handlern)
|
// Textgrößen pro Bildschirmhöhe (wie bei deinen anderen Handlern)
|
||||||
setTextSizePercentOfScreenHeight(questionTextView, 0.03f) // Überschrift
|
ViewUtils.setTextSizePercentOfScreenHeight(questionTextView, 0.03f)
|
||||||
setTextSizePercentOfScreenHeight(questionTitle, 0.03f) // Frage
|
ViewUtils.setTextSizePercentOfScreenHeight(questionTitle, 0.03f)
|
||||||
|
|
||||||
container.removeAllViews()
|
container.removeAllViews()
|
||||||
|
|
||||||
@ -210,10 +211,4 @@ class HandlerMultiCheckboxQuestion(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,14 +5,13 @@ import android.view.View
|
|||||||
import android.text.Html
|
import android.text.Html
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import android.util.TypedValue
|
|
||||||
import androidx.core.widget.TextViewCompat // <— hinzugefügt
|
|
||||||
import com.dano.test1.questionnaire.GlobalValues
|
import com.dano.test1.questionnaire.GlobalValues
|
||||||
import com.dano.test1.LanguageManager
|
import com.dano.test1.LanguageManager
|
||||||
import com.dano.test1.MyApp
|
import com.dano.test1.MyApp
|
||||||
import com.dano.test1.questionnaire.QuestionHandler
|
import com.dano.test1.questionnaire.QuestionHandler
|
||||||
import com.dano.test1.questionnaire.QuestionItem
|
import com.dano.test1.questionnaire.QuestionItem
|
||||||
import com.dano.test1.R
|
import com.dano.test1.R
|
||||||
|
import com.dano.test1.utils.ViewUtils
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Zweck:
|
Zweck:
|
||||||
@ -47,11 +46,8 @@ class HandlerRadioQuestion(
|
|||||||
Html.fromHtml(LanguageManager.getText(languageID, it), Html.FROM_HTML_MODE_LEGACY)
|
Html.fromHtml(LanguageManager.getText(languageID, it), Html.FROM_HTML_MODE_LEGACY)
|
||||||
} ?: ""
|
} ?: ""
|
||||||
|
|
||||||
//
|
ViewUtils.setTextSizePercentOfScreenHeight(questionTextView, 0.03f)
|
||||||
// Titel/Frage: 3% der Bildschirmhöhe
|
ViewUtils.setTextSizePercentOfScreenHeight(questionTitle, 0.03f)
|
||||||
setTextSizePercentOfScreenHeight(questionTextView, 0.03f)
|
|
||||||
setTextSizePercentOfScreenHeight(questionTitle, 0.03f)
|
|
||||||
// ===================================================
|
|
||||||
|
|
||||||
radioGroup.removeAllViews()
|
radioGroup.removeAllViews()
|
||||||
|
|
||||||
@ -61,7 +57,7 @@ class HandlerRadioQuestion(
|
|||||||
tag = option.key
|
tag = option.key
|
||||||
|
|
||||||
// RadioButton-Text analog zu EditTexts: 2.5% der Bildschirmhöhe
|
// RadioButton-Text analog zu EditTexts: 2.5% der Bildschirmhöhe
|
||||||
setTextSizePercentOfScreenHeight(this, 0.025f)
|
ViewUtils.setTextSizePercentOfScreenHeight(this, 0.025f)
|
||||||
|
|
||||||
layoutParams = RadioGroup.LayoutParams(
|
layoutParams = RadioGroup.LayoutParams(
|
||||||
RadioGroup.LayoutParams.MATCH_PARENT,
|
RadioGroup.LayoutParams.MATCH_PARENT,
|
||||||
@ -143,15 +139,6 @@ class HandlerRadioQuestion(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setzt Textgröße prozentual zur Bildschirmhöhe (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 restorePreviousAnswer(radioGroup: RadioGroup) {
|
private fun restorePreviousAnswer(radioGroup: RadioGroup) {
|
||||||
question.question?.let { questionKey ->
|
question.question?.let { questionKey ->
|
||||||
val savedAnswer = answers[questionKey] as? String
|
val savedAnswer = answers[questionKey] as? String
|
||||||
|
|||||||
@ -2,13 +2,8 @@ package com.dano.test1.questionnaire.handlers
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.Gravity
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.widget.TextViewCompat
|
|
||||||
import com.dano.test1.ui.Countries
|
import com.dano.test1.ui.Countries
|
||||||
import com.dano.test1.questionnaire.GlobalValues
|
import com.dano.test1.questionnaire.GlobalValues
|
||||||
import com.dano.test1.LanguageManager
|
import com.dano.test1.LanguageManager
|
||||||
@ -16,6 +11,7 @@ import com.dano.test1.MyApp
|
|||||||
import com.dano.test1.questionnaire.QuestionHandler
|
import com.dano.test1.questionnaire.QuestionHandler
|
||||||
import com.dano.test1.questionnaire.QuestionItem
|
import com.dano.test1.questionnaire.QuestionItem
|
||||||
import com.dano.test1.R
|
import com.dano.test1.R
|
||||||
|
import com.dano.test1.utils.ViewUtils
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Zweck:
|
Zweck:
|
||||||
@ -50,9 +46,9 @@ class HandlerStringSpinner(
|
|||||||
questionTextView.text = question.question?.let { LanguageManager.getText(languageID, it) } ?: ""
|
questionTextView.text = question.question?.let { LanguageManager.getText(languageID, it) } ?: ""
|
||||||
textView.text = question.textKey?.let { LanguageManager.getText(languageID, it) } ?: ""
|
textView.text = question.textKey?.let { LanguageManager.getText(languageID, it) } ?: ""
|
||||||
|
|
||||||
// Textgrößen prozentual zur Bildschirmhöhe (wie im HandlerRadioQuestion)
|
// Textgrößen prozentual zur Bildschirmhöhe
|
||||||
setTextSizePercentOfScreenHeight(textView, 0.03f)
|
ViewUtils.setTextSizePercentOfScreenHeight(textView, 0.03f)
|
||||||
setTextSizePercentOfScreenHeight(questionTextView, 0.03f)
|
ViewUtils.setTextSizePercentOfScreenHeight(questionTextView, 0.03f)
|
||||||
|
|
||||||
val options = buildOptionsList()
|
val options = buildOptionsList()
|
||||||
|
|
||||||
@ -60,7 +56,7 @@ class HandlerStringSpinner(
|
|||||||
val savedSelection = question.question?.let { answers[it] as? String }
|
val savedSelection = question.question?.let { answers[it] as? String }
|
||||||
|
|
||||||
// Spinner aufsetzen
|
// Spinner aufsetzen
|
||||||
setupSpinner(spinner, options, savedSelection)
|
ViewUtils.setupResponsiveSpinner(context, spinner, options, savedSelection)
|
||||||
|
|
||||||
// Falls noch keine Antwort im Map: aus DB laden
|
// Falls noch keine Antwort im Map: aus DB laden
|
||||||
val answerMapKey = question.question ?: (question.id ?: "")
|
val answerMapKey = question.question ?: (question.id ?: "")
|
||||||
@ -127,73 +123,4 @@ class HandlerStringSpinner(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Textgröße prozentual zur Bildschirmhöhe setzen und AutoSize deaktivieren
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spinner-Adapter mit dynamischer Schrift & stabiler Dropdown-Zeilenhöhe (kein Abschneiden)
|
|
||||||
private fun <T> setupSpinner(spinner: Spinner, items: List<T>, selectedItem: T?) {
|
|
||||||
val dm = context.resources.displayMetrics
|
|
||||||
|
|
||||||
fun spFromScreenHeight(percent: Float): Float =
|
|
||||||
(dm.heightPixels * percent) / dm.scaledDensity
|
|
||||||
fun pxFromSp(sp: Float): Int = (sp * dm.scaledDensity).toInt()
|
|
||||||
|
|
||||||
// Schrift & abgeleitete Höhen (wie beim Value-Spinner-Fix)
|
|
||||||
val textSp = spFromScreenHeight(0.0275f) // ~2.75% der Bildschirmhöhe
|
|
||||||
val textPx = pxFromSp(textSp)
|
|
||||||
val vPadPx = (textPx * 0.50f).toInt() // vertikales Padding
|
|
||||||
val rowHeight = (textPx * 2.20f + 2 * vPadPx).toInt() // feste Zeilenhöhe, verhindert Abschneiden
|
|
||||||
|
|
||||||
val adapter = object : ArrayAdapter<T>(context, android.R.layout.simple_spinner_item, items) {
|
|
||||||
private fun styleRow(tv: TextView, forceHeight: Boolean) {
|
|
||||||
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSp)
|
|
||||||
tv.includeFontPadding = true
|
|
||||||
tv.setLineSpacing(0f, 1.2f)
|
|
||||||
tv.gravity = (tv.gravity and Gravity.HORIZONTAL_GRAVITY_MASK) or Gravity.CENTER_VERTICAL
|
|
||||||
tv.setPadding(tv.paddingLeft, vPadPx, tv.paddingRight, vPadPx)
|
|
||||||
tv.minHeight = rowHeight
|
|
||||||
tv.isSingleLine = true
|
|
||||||
if (forceHeight) {
|
|
||||||
val lp = tv.layoutParams
|
|
||||||
if (lp == null || lp.height <= 0) {
|
|
||||||
tv.layoutParams = AbsListView.LayoutParams(
|
|
||||||
AbsListView.LayoutParams.MATCH_PARENT, rowHeight
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
lp.height = rowHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
|
||||||
val v = super.getView(position, convertView, parent) as TextView
|
|
||||||
styleRow(v, forceHeight = false) // ausgewählte Ansicht
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
|
|
||||||
val v = super.getDropDownView(position, convertView, parent) as TextView
|
|
||||||
styleRow(v, forceHeight = true) // Dropdown-Zeilen: Höhe erzwingen
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
|
||||||
spinner.adapter = adapter
|
|
||||||
|
|
||||||
// Spinner selbst ausreichend hoch machen
|
|
||||||
spinner.setPadding(spinner.paddingLeft, vPadPx, spinner.paddingRight, vPadPx)
|
|
||||||
spinner.minimumHeight = rowHeight
|
|
||||||
spinner.requestLayout()
|
|
||||||
|
|
||||||
selectedItem?.let {
|
|
||||||
val index = items.indexOf(it)
|
|
||||||
if (index >= 0) spinner.setSelection(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,18 +2,15 @@ package com.dano.test1.questionnaire.handlers
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.Gravity
|
|
||||||
import androidx.core.widget.TextViewCompat // <- NEU
|
|
||||||
import com.dano.test1.questionnaire.GlobalValues
|
import com.dano.test1.questionnaire.GlobalValues
|
||||||
import com.dano.test1.LanguageManager
|
import com.dano.test1.LanguageManager
|
||||||
import com.dano.test1.MyApp
|
import com.dano.test1.MyApp
|
||||||
import com.dano.test1.questionnaire.QuestionHandler
|
import com.dano.test1.questionnaire.QuestionHandler
|
||||||
import com.dano.test1.questionnaire.QuestionItem
|
import com.dano.test1.questionnaire.QuestionItem
|
||||||
import com.dano.test1.R
|
import com.dano.test1.R
|
||||||
|
import com.dano.test1.utils.ViewUtils
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Zweck:
|
Zweck:
|
||||||
@ -50,10 +47,8 @@ class HandlerValueSpinner(
|
|||||||
questionTextView.text = question.question?.let { LanguageManager.getText(languageID, it) } ?: ""
|
questionTextView.text = question.question?.let { LanguageManager.getText(languageID, it) } ?: ""
|
||||||
textView.text = question.textKey?.let { LanguageManager.getText(languageID, it) } ?: ""
|
textView.text = question.textKey?.let { LanguageManager.getText(languageID, it) } ?: ""
|
||||||
|
|
||||||
// Schriftgrößen wie im HandlerRadioQuestion
|
ViewUtils.setTextSizePercentOfScreenHeight(textView, 0.03f)
|
||||||
// Titel/Frage: 3% der Bildschirmhöhe
|
ViewUtils.setTextSizePercentOfScreenHeight(questionTextView, 0.03f)
|
||||||
setTextSizePercentOfScreenHeight(textView, 0.03f)
|
|
||||||
setTextSizePercentOfScreenHeight(questionTextView, 0.03f)
|
|
||||||
|
|
||||||
val prompt = LanguageManager.getText(languageID, "choose_answer")
|
val prompt = LanguageManager.getText(languageID, "choose_answer")
|
||||||
val spinnerItems: List<String> = listOf(prompt) + if (question.range != null) {
|
val spinnerItems: List<String> = listOf(prompt) + if (question.range != null) {
|
||||||
@ -63,7 +58,7 @@ class HandlerValueSpinner(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val savedValue = question.question?.let { answers[it] as? String }
|
val savedValue = question.question?.let { answers[it] as? String }
|
||||||
setupSpinner(spinner, spinnerItems, savedValue)
|
ViewUtils.setupResponsiveSpinner(context, spinner, spinnerItems, savedValue)
|
||||||
|
|
||||||
//DB-Abfrage falls noch keine Antwort im Map existiert
|
//DB-Abfrage falls noch keine Antwort im Map existiert
|
||||||
val answerMapKey = question.question ?: (question.id ?: "")
|
val answerMapKey = question.question ?: (question.id ?: "")
|
||||||
@ -134,72 +129,4 @@ class HandlerValueSpinner(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setzt Textgröße prozentual zur Bildschirmhöhe (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 <T> setupSpinner(spinner: Spinner, items: List<T>, selectedItem: T?) {
|
|
||||||
val dm = context.resources.displayMetrics
|
|
||||||
|
|
||||||
fun spFromScreenHeight(percent: Float): Float =
|
|
||||||
(dm.heightPixels * percent) / dm.scaledDensity
|
|
||||||
fun pxFromSp(sp: Float): Int = (sp * dm.scaledDensity).toInt()
|
|
||||||
|
|
||||||
// Schrift & abgeleitete Höhen
|
|
||||||
val textSp = spFromScreenHeight(0.0275f) // ~2.75% der Bildschirmhöhe
|
|
||||||
val textPx = pxFromSp(textSp)
|
|
||||||
val vPadPx = (textPx * 0.50f).toInt() // vertikales Padding
|
|
||||||
val rowHeight = (textPx * 2.20f + 2 * vPadPx).toInt() // feste Zeilenhöhe
|
|
||||||
|
|
||||||
val adapter = object : ArrayAdapter<T>(context, android.R.layout.simple_spinner_item, items) {
|
|
||||||
private fun styleRow(tv: TextView, forceHeight: Boolean) {
|
|
||||||
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSp)
|
|
||||||
tv.includeFontPadding = true
|
|
||||||
tv.setLineSpacing(0f, 1.2f)
|
|
||||||
tv.gravity = (tv.gravity and Gravity.HORIZONTAL_GRAVITY_MASK) or Gravity.CENTER_VERTICAL
|
|
||||||
tv.setPadding(tv.paddingLeft, vPadPx, tv.paddingRight, vPadPx)
|
|
||||||
tv.minHeight = rowHeight
|
|
||||||
tv.isSingleLine = true
|
|
||||||
if (forceHeight) {
|
|
||||||
val lp = tv.layoutParams
|
|
||||||
if (lp == null || lp.height <= 0) {
|
|
||||||
tv.layoutParams = AbsListView.LayoutParams(
|
|
||||||
AbsListView.LayoutParams.MATCH_PARENT, rowHeight
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
lp.height = rowHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
|
||||||
val v = super.getView(position, convertView, parent) as TextView
|
|
||||||
styleRow(v, forceHeight = false) // ausgewählte Ansicht
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
|
|
||||||
val v = super.getDropDownView(position, convertView, parent) as TextView
|
|
||||||
styleRow(v, forceHeight = true) // Dropdown-Zeilen: Höhe erzwingen
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
|
||||||
spinner.adapter = adapter
|
|
||||||
|
|
||||||
// Spinner selbst ausreichend hoch machen
|
|
||||||
spinner.setPadding(spinner.paddingLeft, vPadPx, spinner.paddingRight, vPadPx)
|
|
||||||
spinner.minimumHeight = rowHeight
|
|
||||||
spinner.requestLayout()
|
|
||||||
|
|
||||||
selectedItem?.let {
|
|
||||||
val index = items.indexOf(it)
|
|
||||||
if (index >= 0) spinner.setSelection(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import android.util.Log
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import com.dano.test1.data.ExcelExportService
|
import com.dano.test1.data.ExcelExportService
|
||||||
|
import com.dano.test1.utils.ViewUtils
|
||||||
import com.dano.test1.LanguageManager
|
import com.dano.test1.LanguageManager
|
||||||
import com.dano.test1.MainActivity
|
import com.dano.test1.MainActivity
|
||||||
import com.dano.test1.MyApp
|
import com.dano.test1.MyApp
|
||||||
@ -15,7 +16,6 @@ import com.dano.test1.data.HeaderOrderRepository
|
|||||||
import com.dano.test1.data.Question
|
import com.dano.test1.data.Question
|
||||||
import com.dano.test1.data.Questionnaire
|
import com.dano.test1.data.Questionnaire
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlin.math.roundToInt
|
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
|
|
||||||
class DatabaseButtonHandler(
|
class DatabaseButtonHandler(
|
||||||
@ -420,10 +420,7 @@ class DatabaseButtonHandler(
|
|||||||
bgColor?.let { setBackgroundColor(it) }
|
bgColor?.let { setBackgroundColor(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun dp(value: Int): Int {
|
private fun dp(value: Int): Int = ViewUtils.dp(activity, value)
|
||||||
val density = activity.resources.displayMetrics.density
|
|
||||||
return (value * density).roundToInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T : View> requireView(id: Int, name: String): T {
|
private fun <T : View> requireView(id: Int, name: String): T {
|
||||||
val v = activity.findViewById<T>(id)
|
val v = activity.findViewById<T>(id)
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import org.json.JSONObject
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.dano.test1.utils.ViewUtils
|
||||||
|
|
||||||
|
|
||||||
var RHS_POINTS: Int? = null
|
var RHS_POINTS: Int? = null
|
||||||
@ -572,7 +573,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun dp(v: Int): Int = (v * activity.resources.displayMetrics.density).toInt()
|
private fun dp(v: Int): Int = ViewUtils.dp(activity, v)
|
||||||
|
|
||||||
private fun isCompleted(button: Button): Boolean {
|
private fun isCompleted(button: Button): Boolean {
|
||||||
val fileName = questionnaireFiles[button] ?: return false
|
val fileName = questionnaireFiles[button] ?: return false
|
||||||
@ -664,16 +665,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun lockCoachCodeField() {
|
private fun lockCoachCodeField() {
|
||||||
coachEditText.isFocusable = false
|
ViewUtils.lockEditField(coachEditText)
|
||||||
coachEditText.isFocusableInTouchMode = false
|
|
||||||
coachEditText.isCursorVisible = false
|
|
||||||
coachEditText.keyListener = null
|
|
||||||
coachEditText.isLongClickable = false
|
|
||||||
coachEditText.isClickable = false
|
|
||||||
coachEditText.setBackgroundResource(R.drawable.bg_field_locked)
|
|
||||||
coachEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_lock_24, 0)
|
|
||||||
coachEditText.compoundDrawablePadding = dp(8)
|
|
||||||
coachEditText.alpha = 0.95f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun applySessionAgeHighlight(ageMs: Long) {
|
private fun applySessionAgeHighlight(ageMs: Long) {
|
||||||
|
|||||||
110
app/src/main/java/com/dano/test1/utils/ViewUtils.kt
Normal file
110
app/src/main/java/com/dano/test1/utils/ViewUtils.kt
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package com.dano.test1.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.AbsListView
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.EditText
|
||||||
|
import android.widget.Spinner
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.widget.TextViewCompat
|
||||||
|
import com.dano.test1.R
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
object ViewUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the text size of a TextView to a percentage of the screen height (in sp).
|
||||||
|
* Disables auto-sizing to prevent conflicts.
|
||||||
|
*/
|
||||||
|
fun setTextSizePercentOfScreenHeight(view: TextView, percentOfHeight: Float) {
|
||||||
|
val dm = view.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)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up a Spinner with a responsive, styled adapter.
|
||||||
|
* Font size and row height are derived from screen height to prevent clipping.
|
||||||
|
*/
|
||||||
|
fun <T> setupResponsiveSpinner(context: Context, spinner: Spinner, items: List<T>, selectedItem: T?) {
|
||||||
|
val dm = context.resources.displayMetrics
|
||||||
|
|
||||||
|
fun spFromScreenHeight(percent: Float): Float = (dm.heightPixels * percent) / dm.scaledDensity
|
||||||
|
fun pxFromSp(sp: Float): Int = (sp * dm.scaledDensity).toInt()
|
||||||
|
|
||||||
|
val textSp = spFromScreenHeight(0.0275f)
|
||||||
|
val textPx = pxFromSp(textSp)
|
||||||
|
val vPadPx = (textPx * 0.50f).toInt()
|
||||||
|
val rowHeight = (textPx * 2.20f + 2 * vPadPx).toInt()
|
||||||
|
|
||||||
|
val adapter = object : ArrayAdapter<T>(context, android.R.layout.simple_spinner_item, items) {
|
||||||
|
private fun styleRow(tv: TextView, forceHeight: Boolean) {
|
||||||
|
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSp)
|
||||||
|
tv.includeFontPadding = true
|
||||||
|
tv.setLineSpacing(0f, 1.2f)
|
||||||
|
tv.gravity = (tv.gravity and Gravity.HORIZONTAL_GRAVITY_MASK) or Gravity.CENTER_VERTICAL
|
||||||
|
tv.setPadding(tv.paddingLeft, vPadPx, tv.paddingRight, vPadPx)
|
||||||
|
tv.minHeight = rowHeight
|
||||||
|
tv.isSingleLine = true
|
||||||
|
if (forceHeight) {
|
||||||
|
val lp = tv.layoutParams
|
||||||
|
if (lp == null || lp.height <= 0) {
|
||||||
|
tv.layoutParams = AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, rowHeight)
|
||||||
|
} else {
|
||||||
|
lp.height = rowHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||||
|
val v = super.getView(position, convertView, parent) as TextView
|
||||||
|
styleRow(v, forceHeight = false)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||||
|
val v = super.getDropDownView(position, convertView, parent) as TextView
|
||||||
|
styleRow(v, forceHeight = true)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
|
spinner.adapter = adapter
|
||||||
|
spinner.setPadding(spinner.paddingLeft, vPadPx, spinner.paddingRight, vPadPx)
|
||||||
|
spinner.minimumHeight = rowHeight
|
||||||
|
spinner.requestLayout()
|
||||||
|
|
||||||
|
selectedItem?.let {
|
||||||
|
val index = items.indexOf(it)
|
||||||
|
if (index >= 0) spinner.setSelection(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locks an EditText field visually and functionally (e.g. for coach code fields).
|
||||||
|
*/
|
||||||
|
fun lockEditField(field: EditText, dpPadding: Int = 8) {
|
||||||
|
field.isFocusable = false
|
||||||
|
field.isFocusableInTouchMode = false
|
||||||
|
field.isCursorVisible = false
|
||||||
|
field.keyListener = null
|
||||||
|
field.isLongClickable = false
|
||||||
|
field.isClickable = false
|
||||||
|
field.setBackgroundResource(R.drawable.bg_field_locked)
|
||||||
|
field.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_lock_24, 0)
|
||||||
|
field.compoundDrawablePadding = dp(field.context, dpPadding)
|
||||||
|
field.alpha = 0.95f
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts dp to pixels using the given context.
|
||||||
|
*/
|
||||||
|
fun dp(context: Context, value: Int): Int =
|
||||||
|
(value * context.resources.displayMetrics.density).roundToInt()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user