[UI/Timetable] Show subject-based lesson colors. (#141)

* [UI/Timetable] Add timetable config dialog and implement UI options.

* [UI/Timetable] Fix reloading timetable after changing config.

* [UI/Timetable] Fix calculating lesson range boundaries.

* [UI/Timetable] Add coloring subject names.
This commit is contained in:
Kuba Szczodrzyński 2022-10-16 12:47:54 +02:00 committed by GitHub
parent 55369eaa8b
commit e2fd714070
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 80 additions and 5 deletions

View File

@ -84,4 +84,9 @@ class ProfileConfigUI(private val config: ProfileConfig) {
var timetableTrimHourRange: Boolean var timetableTrimHourRange: Boolean
get() { mTimetableTrimHourRange = mTimetableTrimHourRange ?: config.values.get("timetableTrimHourRange", false); return mTimetableTrimHourRange ?: false } get() { mTimetableTrimHourRange = mTimetableTrimHourRange ?: config.values.get("timetableTrimHourRange", false); return mTimetableTrimHourRange ?: false }
set(value) { config.set("timetableTrimHourRange", value); mTimetableTrimHourRange = value } set(value) { config.set("timetableTrimHourRange", value); mTimetableTrimHourRange = value }
private var mTimetableColorSubjectName: Boolean? = null
var timetableColorSubjectName: Boolean
get() { mTimetableColorSubjectName = mTimetableColorSubjectName ?: config.values.get("timetableColorSubjectName", false); return mTimetableColorSubjectName ?: false }
set(value) { config.set("timetableColorSubjectName", value); mTimetableColorSubjectName = value }
} }

View File

@ -4,6 +4,7 @@
package pl.szczodrzynski.edziennik.ui.timetable package pl.szczodrzynski.edziennik.ui.timetable
import android.graphics.drawable.ColorDrawable
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -12,6 +13,7 @@ import android.widget.FrameLayout
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.asynclayoutinflater.view.AsyncLayoutInflater import androidx.asynclayoutinflater.view.AsyncLayoutInflater
import androidx.core.graphics.ColorUtils
import androidx.core.view.* import androidx.core.view.*
import com.linkedin.android.tachyon.DayView import com.linkedin.android.tachyon.DayView
import com.linkedin.android.tachyon.DayViewConfig import com.linkedin.android.tachyon.DayViewConfig
@ -33,6 +35,7 @@ import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.ui.base.lazypager.LazyFragment import pl.szczodrzynski.edziennik.ui.base.lazypager.LazyFragment
import pl.szczodrzynski.edziennik.ui.timetable.TimetableFragment.Companion.DEFAULT_END_HOUR import pl.szczodrzynski.edziennik.ui.timetable.TimetableFragment.Companion.DEFAULT_END_HOUR
import pl.szczodrzynski.edziennik.ui.timetable.TimetableFragment.Companion.DEFAULT_START_HOUR import pl.szczodrzynski.edziennik.ui.timetable.TimetableFragment.Companion.DEFAULT_START_HOUR
import pl.szczodrzynski.edziennik.utils.Colors
import pl.szczodrzynski.edziennik.utils.managers.NoteManager import pl.szczodrzynski.edziennik.utils.managers.NoteManager
import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.utils.models.Time
@ -309,13 +312,36 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope {
lesson.classroom?.let { add(it) } lesson.classroom?.let { add(it) }
}.concat(arrowRight) }.concat(arrowRight)
lb.annotationVisible = manager.getAnnotation(activity, lesson, lb.annotation)
lb.lessonNumber = lesson.displayLessonNumber
val lessonText = val lessonText =
lesson.getNoteSubstituteText(showNotes = true) ?: lesson.displaySubjectName lesson.getNoteSubstituteText(showNotes = true) ?: lesson.displaySubjectName
val (subjectTextPrimary, subjectTextSecondary) = if (profileConfig.timetableColorSubjectName) {
val subjectColor = Colors.stringToMaterialColorCRC(lessonText?.toString() ?: "")
if (lb.annotationVisible) {
lb.subjectContainer.background = ColorDrawable(subjectColor)
} else {
lb.subjectContainer.setBackgroundResource(R.drawable.timetable_subject_color_rounded)
lb.subjectContainer.background.setTintColor(subjectColor)
}
when (ColorUtils.calculateLuminance(subjectColor) > 0.5) {
true -> /* light */ 0xFF000000 to 0xFF666666
false -> /* dark */ 0xFFFFFFFF to 0xFFAAAAAA
}
} else {
lb.subjectContainer.background = null
null to colorSecondary
}
lb.lessonNumber = lesson.displayLessonNumber
if (subjectTextPrimary != null)
lb.lessonNumberText.setTextColor(subjectTextPrimary.toInt())
lb.subjectName.text = lessonText?.let { lb.subjectName.text = lessonText?.let {
if (lesson.type == Lesson.TYPE_CANCELLED || lesson.type == Lesson.TYPE_SHIFTED_SOURCE) if (lesson.type == Lesson.TYPE_CANCELLED || lesson.type == Lesson.TYPE_SHIFTED_SOURCE)
it.asStrikethroughSpannable().asColoredSpannable(colorSecondary) it.asStrikethroughSpannable().asColoredSpannable(subjectTextSecondary.toInt())
else if (subjectTextPrimary != null)
it.asColoredSpannable(subjectTextPrimary.toInt())
else else
it it
} }
@ -342,7 +368,6 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope {
} }
//lb.subjectName.typeface = Typeface.create("sans-serif-light", Typeface.BOLD) //lb.subjectName.typeface = Typeface.create("sans-serif-light", Typeface.BOLD)
lb.annotationVisible = manager.getAnnotation(activity, lesson, lb.annotation)
val lessonNumberMargin = val lessonNumberMargin =
if (lb.annotationVisible) (-8).dp if (lb.annotationVisible) (-8).dp
else 0 else 0

View File

@ -15,6 +15,7 @@ import androidx.core.graphics.ColorUtils;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.util.Arrays; import java.util.Arrays;
import java.util.Random; import java.util.Random;
import java.util.zip.CRC32;
import pl.szczodrzynski.edziennik.data.db.entity.Grade; import pl.szczodrzynski.edziennik.data.db.entity.Grade;
@ -84,6 +85,28 @@ public class Colors {
0xFF6D4C41 0xFF6D4C41
}; };
public static final int[] materialColorsBasic = {
0xFFE53935, 0xFFD81B60, 0xFF8E24AA, 0xFF5E35B1,
0xFF3949AB, 0xFF1E88E5, 0xFF039BE5, 0xFF00ACC1,
0xFF00897B, 0xFF43A047, 0xFF7CB342, 0xFFC0CA33,
0xFFFDD835, 0xFFFFB300, 0xFFFB8C00, 0xFFF4511E,
0xFF6D4C41, 0xFF757575, 0xFF546E7A, 0xFF00E676,
0xFFEF9A9A, 0xFFF48FB1, 0xFFCE93D8, 0xFFB39DDB,
0xFF9FA8DA, 0xFF90CAF9, 0xFF81D4FA, 0xFF80DEEA,
0xFF80CBC4, 0xFFA5D6A7, 0xFFC5E1A5, 0xFFE6EE9C,
0xFFFFF59D, 0xFFFFE082, 0xFFFFCC80, 0xFFFFAB91,
0xFFBCAAA4, 0xFFEEEEEE, 0xFFB0BEC5, 0xFFCCFF90,
};
public static final int[] metroColors = {
0xFF76FF03, 0xFF60A917, 0xFF00C853, 0xFF00ABA9,
0xFF1BA1E2, 0xFF0050EF, 0xFF6A00FF, 0xFFAA00FF,
0xFFF472D0, 0xFFD80073, 0xFFA20025, 0xFFE51400,
0xFFFA6800, 0xFFF0A30A, 0xFFE3C800, 0xFF795548,
0xFF6D8764, 0xFF647687, 0xFF76608A, 0xFFA0522D,
};
/** /**
* Used for teacher's images (e.g. in messages or announcements). * Used for teacher's images (e.g. in messages or announcements).
* @param s teacher's fullName * @param s teacher's fullName
@ -115,6 +138,18 @@ public class Colors {
return materialColors[getRandomNumberInRange(0, materialColors.length-1, seed)]; return materialColors[getRandomNumberInRange(0, materialColors.length-1, seed)];
} }
public static int stringToMaterialColorCRC(String s) {
long seed;
try {
CRC32 crc = new CRC32();
crc.update(s.getBytes());
seed = crc.getValue();
} catch (Exception e) {
seed = 1234;
}
return metroColors[(int) (seed % metroColors.length)];
}
public static int gradeToColor(Grade grade) public static int gradeToColor(Grade grade)
{ {
if (grade.getType() == Grade.TYPE_POINT_SUM) { if (grade.getType() == Grade.TYPE_POINT_SUM) {

View File

@ -44,6 +44,14 @@
android:minHeight="32dp" android:minHeight="32dp"
android:text="@string/timetable_config_show_attendance" /> android:text="@string/timetable_config_show_attendance" />
<com.google.android.material.checkbox.MaterialCheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:checked="@={config.timetableColorSubjectName}"
android:minHeight="32dp"
android:text="@string/timetable_config_color_subject_name" />
<com.google.android.material.checkbox.MaterialCheckBox <com.google.android.material.checkbox.MaterialCheckBox
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -45,14 +45,15 @@
tools:visibility="gone" /> tools:visibility="gone" />
<LinearLayout <LinearLayout
android:id="@+id/subjectContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="top" android:layout_gravity="top"
android:baselineAligned="false" android:baselineAligned="false"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingHorizontal="8dp" android:paddingHorizontal="8dp"
android:paddingVertical="4dp"> android:paddingVertical="4dp"
<!--tools:background="@drawable/timetable_subject_color_rounded"--> tools:background="@drawable/timetable_subject_color_rounded">
<com.mikepenz.iconics.view.IconicsTextView <com.mikepenz.iconics.view.IconicsTextView
android:id="@+id/subjectName" android:id="@+id/subjectName"

View File

@ -1540,5 +1540,6 @@
<string name="menu_timetable_config">Ustawienia planu lekcji</string> <string name="menu_timetable_config">Ustawienia planu lekcji</string>
<string name="timetable_config_show_events">Pokazuj wydarzenia przy lekcjach</string> <string name="timetable_config_show_events">Pokazuj wydarzenia przy lekcjach</string>
<string name="timetable_config_show_attendance">Pokazuj rodzaj obecności na lekcji</string> <string name="timetable_config_show_attendance">Pokazuj rodzaj obecności na lekcji</string>
<string name="timetable_config_color_subject_name">Koloruj nazwę przedmiotu</string>
<string name="timetable_config_trim_hour_range">Nie pokazuj godzin bez lekcji</string> <string name="timetable_config_trim_hour_range">Nie pokazuj godzin bez lekcji</string>
</resources> </resources>