Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ android {
applicationId "org.ole.planet.myplanet"
minSdk = 26
targetSdk = 36
versionCode = 5590
versionName = "0.55.90"
versionCode = 5591
versionName = "0.55.91"
ndkVersion = '26.3.11579264'
vectorDrawables.useSupportLibrary = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ open class RealmExamQuestion : RealmObject() {
var marks: String? = null
var choices: String? = null
var hasOtherOption: Boolean = false
var scaleMax: Int = 9
private fun setCorrectChoiceArray(array: JsonArray, question: RealmExamQuestion?) {
for (i in 0 until array.size()) {
question?.correctChoice?.add(JsonUtils.getString(array, i).lowercase(Locale.getDefault()))
Expand Down Expand Up @@ -90,6 +91,7 @@ open class RealmExamQuestion : RealmObject() {
}

hasOtherOption = JsonUtils.getBoolean("hasOtherOption", question)
scaleMax = JsonUtils.getInt("scaleMax", question).let { if (it <= 0) 9 else it }
val isMultipleChoice = type?.startsWith("select") == true && question.has("choices")
if (isMultipleChoice) {
insertCorrectChoice(question["choices"].asJsonArray, question, this)
Expand Down
134 changes: 100 additions & 34 deletions app/src/main/java/org/ole/planet/myplanet/ui/exam/ExamTakingFragment.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
package org.ole.planet.myplanet.ui.exam

import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.StateListDrawable
import android.os.Bundle
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.CompoundButton
import android.widget.LinearLayout
import android.widget.RadioButton
import android.widget.Toast
import androidx.core.content.ContextCompat
Expand Down Expand Up @@ -329,7 +335,7 @@ class ExamTakingFragment : BaseExamFragment(), View.OnClickListener, CompoundBut
}
question?.type.equals("ratingScale", ignoreCase = true) -> {
binding.llRatingScale.visibility = View.VISIBLE
setupRatingScale(ans)
setupRatingScale(question, ans)
}
}
binding.tvHeader.text = question?.header
Expand Down Expand Up @@ -379,28 +385,49 @@ class ExamTakingFragment : BaseExamFragment(), View.OnClickListener, CompoundBut
}

private var selectedRatingButton: Button? = null

private fun setupRatingScale(oldAnswer: String) {
val ratingButtons = listOf(
binding.rbRating1,
binding.rbRating2,
binding.rbRating3,
binding.rbRating4,
binding.rbRating5,
binding.rbRating6,
binding.rbRating7,
binding.rbRating8,
binding.rbRating9
)

ratingButtons.forEachIndexed { index, button ->
private var dynamicRatingButtons: List<Button> = emptyList()

private fun setupRatingScale(question: RealmExamQuestion?, oldAnswer: String) {
val scaleMax = (question?.scaleMax ?: 0).let { if (it <= 0) 9 else it }
binding.llRatingScale.removeAllViews()
dynamicRatingButtons = emptyList()

val buttonSizePx = (60 * resources.displayMetrics.density).toInt()
val marginPx = (8 * resources.displayMetrics.density).toInt()
val buttonsPerRow = 3
val buttons = mutableListOf<Button>()
var currentRow: LinearLayout? = null

val useGradient = scaleMax == 9

for (i in 1..scaleMax) {
val positionInRow = (i - 1) % buttonsPerRow
if (positionInRow == 0) {
currentRow = LinearLayout(requireContext()).apply {
orientation = LinearLayout.HORIZONTAL
gravity = Gravity.CENTER
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
).also { it.bottomMargin = marginPx }
}
binding.llRatingScale.addView(currentRow)
}
val isLastInRow = positionInRow == buttonsPerRow - 1 || i == scaleMax
val ratio = if (scaleMax > 1) (i - 1).toFloat() / (scaleMax - 1) else 0f
val button = createRatingButton(i, ratio, buttonSizePx, if (isLastInRow) 0 else marginPx, useGradient)
currentRow?.addView(button)
buttons.add(button)
}

dynamicRatingButtons = buttons

buttons.forEachIndexed { index, button ->
button.setOnClickListener {
selectedRatingButton?.isSelected = false

button.isSelected = true
selectedRatingButton = button
ans = (index + 1).toString()

updateNavButtons()
}
}
Expand All @@ -409,24 +436,62 @@ class ExamTakingFragment : BaseExamFragment(), View.OnClickListener, CompoundBut
selectRatingValue(oldAnswer.toIntOrNull() ?: 1)
}
}

private fun selectRatingValue(value: Int) {
val ratingButtons = listOf(
binding.rbRating1,
binding.rbRating2,
binding.rbRating3,
binding.rbRating4,
binding.rbRating5,
binding.rbRating6,
binding.rbRating7,
binding.rbRating8,
binding.rbRating9
)

private fun createRatingButton(number: Int, colorRatio: Float, sizePx: Int, marginEndPx: Int, useGradient: Boolean): Button {
val selectedColor = ContextCompat.getColor(requireContext(), R.color.colorPrimary)
val cornerPx = 8 * resources.displayMetrics.density
val strokePx = (2 * resources.displayMetrics.density).toInt()

val unselectedBg: Int
val unselectedStroke: Int
if (useGradient) {
unselectedBg = interpolateColor(0xFFFFE9EA.toInt(), 0xFFE9FBE9.toInt(), colorRatio)
unselectedStroke = unselectedBg
} else {
unselectedBg = ContextCompat.getColor(requireContext(), R.color.card_bg)
unselectedStroke = ContextCompat.getColor(requireContext(), R.color.daynight_textColor)
}

fun makeShape(fillColor: Int, strokeColor: Int) = GradientDrawable().apply {
shape = GradientDrawable.RECTANGLE
cornerRadius = cornerPx
setColor(fillColor)
setStroke(strokePx, strokeColor)
}

val stateList = StateListDrawable().apply {
addState(intArrayOf(android.R.attr.state_selected), makeShape(selectedColor, selectedColor))
addState(intArrayOf(android.R.attr.state_pressed), makeShape(selectedColor, selectedColor))
addState(intArrayOf(), makeShape(unselectedBg, unselectedStroke))
}

return Button(requireContext()).apply {
text = number.toString()
textSize = 16f
setTypeface(null, Typeface.BOLD)
setTextColor(ContextCompat.getColorStateList(requireContext(), R.color.rating_button_text_color))
background = stateList
minHeight = 0
minWidth = 0
setPadding(0, 0, 0, 0)
layoutParams = LinearLayout.LayoutParams(sizePx, sizePx).apply {
marginEnd = marginEndPx
}
}
}

private fun interpolateColor(start: Int, end: Int, ratio: Float): Int {
val r = (Color.red(start) + (Color.red(end) - Color.red(start)) * ratio).toInt()
val g = (Color.green(start) + (Color.green(end) - Color.green(start)) * ratio).toInt()
val b = (Color.blue(start) + (Color.blue(end) - Color.blue(start)) * ratio).toInt()
return Color.rgb(r, g, b)
}

private fun selectRatingValue(value: Int) {
selectedRatingButton?.isSelected = false

if (value in 1..9) {
val button = ratingButtons[value - 1]
val buttons = dynamicRatingButtons
if (value in 1..buttons.size) {
val button = buttons[value - 1]
button.isSelected = true
selectedRatingButton = button
}
Expand Down Expand Up @@ -751,6 +816,7 @@ class ExamTakingFragment : BaseExamFragment(), View.OnClickListener, CompoundBut
}
answerTextWatcher?.let { binding.etAnswer.removeTextChangedListener(it) }
selectedRatingButton = null
dynamicRatingButtons = emptyList()
_binding = null
}
}
123 changes: 2 additions & 121 deletions app/src/main/res/layout/fragment_exam_taking.xml
Original file line number Diff line number Diff line change
Expand Up @@ -139,131 +139,12 @@
<LinearLayout
android:id="@+id/ll_rating_scale"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/padding_large"
android:visibility="gone">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_gravity="center">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="8dp">

<Button
android:id="@+id/rb_rating_1"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginEnd="8dp"
android:background="@drawable/bg_rating_button_1"
android:text="1"
android:textColor="@color/rating_button_text_color"
android:textSize="16sp"
android:textStyle="bold" />
<Button
android:id="@+id/rb_rating_2"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginEnd="8dp"
android:background="@drawable/bg_rating_button_2"
android:text="2"
android:textColor="@color/rating_button_text_color"
android:textSize="16sp"
android:textStyle="bold" />
<Button
android:id="@+id/rb_rating_3"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/bg_rating_button_3"
android:text="3"
android:textColor="@color/rating_button_text_color"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="8dp">

<Button
android:id="@+id/rb_rating_4"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginEnd="8dp"
android:background="@drawable/bg_rating_button_4"
android:text="4"
android:textColor="@color/rating_button_text_color"
android:textSize="16sp"
android:textStyle="bold" />
<Button
android:id="@+id/rb_rating_5"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginEnd="8dp"
android:background="@drawable/bg_rating_button_5"
android:text="5"
android:textColor="@color/rating_button_text_color"
android:textSize="16sp"
android:textStyle="bold" />
<Button
android:id="@+id/rb_rating_6"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/bg_rating_button_6"
android:text="6"
android:textColor="@color/rating_button_text_color"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">

<Button
android:id="@+id/rb_rating_7"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginEnd="8dp"
android:background="@drawable/bg_rating_button_7"
android:text="7"
android:textColor="@color/rating_button_text_color"
android:textSize="16sp"
android:textStyle="bold" />
<Button
android:id="@+id/rb_rating_8"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginEnd="8dp"
android:background="@drawable/bg_rating_button_8"
android:text="8"
android:textColor="@color/rating_button_text_color"
android:textSize="16sp"
android:textStyle="bold" />
<Button
android:id="@+id/rb_rating_9"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/bg_rating_button_9"
android:text="9"
android:textColor="@color/rating_button_text_color"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
android:visibility="gone" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>

Expand Down
Loading