Add theming system

Standardize theming across the app into ThemeUtils.
This commit is contained in:
OxygenCobalt 2020-09-01 07:37:49 -06:00
parent d5e6b813a9
commit 8f850f2288
13 changed files with 171 additions and 32 deletions

View file

@ -10,7 +10,7 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/BaseTheme">
android:theme="@style/Theme.Base">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View file

@ -1,16 +1,27 @@
package org.oxycblt.auxio
import android.content.Context
import android.os.Bundle
import android.util.AttributeSet
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import org.oxycblt.auxio.theme.accent
class MainActivity : AppCompatActivity() {
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
setTheme(accent.second)
return super.onCreateView(name, context, attrs)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
Log.d(this::class.simpleName, "Activity Created.")
}

View file

@ -15,8 +15,9 @@ import com.google.android.material.tabs.TabLayoutMediator
import org.oxycblt.auxio.databinding.FragmentMainBinding
import org.oxycblt.auxio.library.LibraryFragment
import org.oxycblt.auxio.songs.SongsFragment
import org.oxycblt.auxio.theme.getAccentTransparency
import org.oxycblt.auxio.theme.getDeselectedTransparency
import org.oxycblt.auxio.theme.accent
import org.oxycblt.auxio.theme.getInactiveAlpha
import org.oxycblt.auxio.theme.getTransparentAccent
import org.oxycblt.auxio.theme.toColor
class MainFragment : Fragment() {
@ -27,12 +28,14 @@ class MainFragment : Fragment() {
private val songsFragment: SongsFragment by lazy { SongsFragment() }
private val colorSelected: Int by lazy {
R.color.blue.toColor(requireContext())
accent.first.toColor(requireContext())
}
private val colorDeselected: Int by lazy {
getAccentTransparency(
requireContext(), R.color.blue, getDeselectedTransparency(R.color.blue)
getTransparentAccent(
requireContext(),
accent.first,
getInactiveAlpha(accent.first)
)
}
@ -83,10 +86,6 @@ class MainFragment : Fragment() {
}
)
binding.tabs.getTabAt(
binding.viewPager.offscreenPageLimit
)
Log.d(this::class.simpleName, "Fragment Created.")
return binding.root

View file

@ -4,8 +4,8 @@ import android.graphics.drawable.ColorDrawable
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.R
import org.oxycblt.auxio.theme.getAccentTransparency
import org.oxycblt.auxio.theme.getDayNightTransparency
import org.oxycblt.auxio.theme.getDayNightAlpha
import org.oxycblt.auxio.theme.getTransparentAccent
// Apply a custom vertical divider
fun RecyclerView.applyDivider() {
@ -16,8 +16,8 @@ fun RecyclerView.applyDivider() {
div.setDrawable(
ColorDrawable(
getAccentTransparency(
context, R.color.divider_color, getDayNightTransparency()
getTransparentAccent(
context, R.color.divider_color, getDayNightAlpha()
)
)
)

View file

@ -6,18 +6,43 @@ import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils
import org.oxycblt.auxio.R
fun getDayNightTransparency(): Int {
// Pairs of the base accent and its theme
private val ACCENTS = listOf(
Pair(R.color.red, R.style.Theme_Red),
Pair(R.color.pink, R.style.Theme_Pink),
Pair(R.color.purple, R.style.Theme_Purple),
Pair(R.color.deep_purple, R.style.Theme_DeepPurple),
Pair(R.color.indigo, R.style.Theme_Indigo),
Pair(R.color.blue, R.style.Theme_Blue),
Pair(R.color.light_blue, R.style.Theme_Blue),
Pair(R.color.cyan, R.style.Theme_Cyan),
Pair(R.color.teal, R.style.Theme_Teal),
Pair(R.color.green, R.style.Theme_Green),
Pair(R.color.light_green, R.style.Theme_LightGreen),
Pair(R.color.lime, R.style.Theme_Lime),
Pair(R.color.yellow, R.style.Theme_Yellow),
Pair(R.color.amber, R.style.Theme_Amber),
Pair(R.color.orange, R.style.Theme_Orange),
Pair(R.color.deep_orange, R.style.Theme_DeepOrange),
Pair(R.color.brown, R.style.Theme_Brown),
Pair(R.color.grey, R.style.Theme_Gray),
Pair(R.color.blue_grey, R.style.Theme_BlueGrey)
)
val accent = ACCENTS[5]
fun getDayNightAlpha(): Int {
val isDark = AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES
// Depending on the theme use a different opacity for the divider
return if (isDark) 45 else 85
}
fun getDeselectedTransparency(color: Int): Int {
fun getInactiveAlpha(color: Int): Int {
return if (color == R.color.yellow) 100 else 150
}
fun getAccentTransparency(context: Context, color: Int, alpha: Int): Int {
fun getTransparentAccent(context: Context, color: Int, alpha: Int): Int {
return ColorUtils.setAlphaComponent(
ContextCompat.getColor(context, color),
alpha
@ -28,6 +53,7 @@ fun Int.toColor(context: Context): Int {
return try {
ContextCompat.getColor(context, this)
} catch (e: Exception) {
ContextCompat.getColor(context, android.R.color.white)
// Default to the emergency color [Black] if the loading fails.
ContextCompat.getColor(context, android.R.color.black)
}
}

View file

@ -8,7 +8,7 @@
<shape android:shape="rectangle">
<solid android:color="@android:color/white" />
<corners android:radius="4dp" />
<size android:height="2dp" />
<size android:height="3dp" />
</shape>
</item>
</layer-list>

View file

@ -14,8 +14,7 @@
android:layout_height="?android:attr/actionBarSize"
android:background="?android:attr/windowBackground"
android:elevation="@dimen/elevation_normal"
app:titleTextAppearance="@style/ToolbarStyle"
app:layout_constraintTop_toTopOf="parent"
app:titleTextAppearance="@style/TextAppearance.Toolbar.Bold"
app:title="@string/title_library_fragment" />
<androidx.recyclerview.widget.RecyclerView

View file

@ -20,7 +20,7 @@
android:id="@+id/loading_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateTint="@color/blue"
android:indeterminateTint="?attr/colorPrimary"
android:indeterminateTintMode="src_in"
android:paddingBottom="@dimen/padding_tiny"
app:layout_constraintBottom_toTopOf="@+id/error_text"
@ -28,7 +28,8 @@
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
app:layout_constraintVertical_chainStyle="packed"
tools:indeterminateTint="@color/blue" />
<TextView
android:id="@+id/error_text"
@ -53,13 +54,14 @@
android:text="@string/label_retry"
android:visibility="gone"
android:fontFamily="@font/inter_semibold"
android:textColor="@color/blue"
android:textColor="?attr/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/error_text"
tools:visibility="visible" />
tools:visibility="visible"
tools:textColor="@color/blue" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -20,6 +20,7 @@
android:layout_height="@dimen/tab_menu_size"
android:layout_gravity="bottom"
android:background="?android:attr/windowBackground"
android:elevation="@dimen/elevation_normal"
app:tabIndicatorColor="?android:attr/colorPrimary"
app:tabGravity="fill"
app:tabMode="fixed"

View file

@ -14,7 +14,7 @@
android:layout_height="?android:attr/actionBarSize"
android:background="?android:attr/windowBackground"
android:elevation="@dimen/elevation_normal"
app:titleTextAppearance="@style/ToolbarStyle"
app:titleTextAppearance="@style/TextAppearance.Toolbar.Bold"
app:layout_constraintTop_toTopOf="parent"
app:title="@string/title_all_songs" />

View file

@ -10,7 +10,7 @@
<dimen name="cover_size_compact">44dp</dimen>
<dimen name="cover_size_normal">56dp</dimen>
<dimen name="tab_menu_size">38dp</dimen>
<dimen name="tab_menu_size">40dp</dimen>
<dimen name="elevation_normal">4dp</dimen>
</resources>

View file

@ -1,15 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base theme -->
<style name="BaseTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:colorPrimary">@color/blue</item>
<style name="Theme.Base" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:windowBackground">@color/background</item>
<item name="android:statusBarColor">@android:color/black</item>
<item name="android:fontFamily">@font/inter</item>
</style>
<style name="ToolbarStyle" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
<style name="TextAppearance.Toolbar.Bold" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
<item name="android:fontFamily">@font/inter_black</item>
<item name="android:textColor">@color/blue</item>
<item name="android:textColor">?android:attr/colorPrimary</item>
</style>
</resources>

View file

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.Red" parent="Theme.Base">
<item name="colorPrimary">@color/red</item>
<item name="colorSecondary">@color/red</item>
</style>
<style name="Theme.Pink" parent="Theme.Base">
<item name="colorPrimary">@color/pink</item>
<item name="colorSecondary">@color/pink</item>
</style>
<style name="Theme.Purple" parent="Theme.Base">
<item name="colorPrimary">@color/purple</item>
<item name="colorSecondary">@color/purple</item>
</style>
<style name="Theme.DeepPurple" parent="Theme.Base">
<item name="colorPrimary">@color/deep_purple</item>
<item name="colorSecondary">@color/deep_purple</item>
</style>
<style name="Theme.Indigo" parent="Theme.Base">
<item name="colorPrimary">@color/indigo</item>
<item name="colorSecondary">@color/indigo</item>
</style>
<style name="Theme.Blue" parent="Theme.Base">
<item name="colorPrimary">@color/blue</item>
<item name="colorSecondary">@color/blue</item>
</style>
<style name="Theme.LightBlue" parent="Theme.Base">
<item name="colorPrimary">@color/light_blue</item>
<item name="colorSecondary">@color/light_blue</item>
</style>
<style name="Theme.Cyan" parent="Theme.Base">
<item name="colorPrimary">@color/cyan</item>
<item name="colorSecondary">@color/cyan</item>
</style>
<style name="Theme.Teal" parent="Theme.Base">
<item name="colorPrimary">@color/teal</item>
<item name="colorSecondary">@color/teal</item>
</style>
<style name="Theme.Green" parent="Theme.Base">
<item name="colorPrimary">@color/green</item>
<item name="colorSecondary">@color/green</item>
</style>
<style name="Theme.LightGreen" parent="Theme.Base">
<item name="colorPrimary">@color/light_green</item>
<item name="colorSecondary">@color/light_green</item>
</style>
<style name="Theme.Lime" parent="Theme.Base">
<item name="colorPrimary">@color/lime</item>
<item name="colorSecondary">@color/lime</item>
</style>
<style name="Theme.Yellow" parent="Theme.Base">
<item name="colorPrimary">@color/yellow</item>
<item name="colorSecondary">@color/yellow</item>
</style>
<style name="Theme.Amber" parent="Theme.Base">
<item name="colorPrimary">@color/amber</item>
<item name="colorSecondary">@color/amber</item>
</style>
<style name="Theme.Orange" parent="Theme.Base">
<item name="colorPrimary">@color/orange</item>
<item name="colorSecondary">@color/orange</item>
</style>
<style name="Theme.DeepOrange" parent="Theme.Base">
<item name="colorPrimary">@color/deep_orange</item>
<item name="colorSecondary">@color/deep_orange</item>
</style>
<style name="Theme.Brown" parent="Theme.Base">
<item name="colorPrimary">@color/brown</item>
<item name="colorSecondary">@color/brown</item>
</style>
<style name="Theme.Gray" parent="Theme.Base">
<item name="colorPrimary">@color/grey</item>
<item name="colorSecondary">@color/grey</item>
</style>
<style name="Theme.BlueGrey" parent="Theme.Base">
<item name="colorPrimary">@color/blue_grey</item>
<item name="colorSecondary">@color/blue_grey</item>
</style>
</resources>