Skip to content

Commit

Permalink
DynamicTheme: Rework theme and primary color setup
Browse files Browse the repository at this point in the history
Signed-off-by: Aayush Gupta <[email protected]>
  • Loading branch information
theimpulson committed Apr 4, 2024
1 parent 2e99b7e commit 15b0433
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 0 deletions.
2 changes: 2 additions & 0 deletions app/src/main/java/com/android/calendar/AboutActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package com.android.calendar

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.android.calendar.theme.applyThemeAndPrimaryColor

import ws.xsoh.etar.R
import ws.xsoh.etar.databinding.SimpleFrameLayoutMaterialBinding

class AboutActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
applyThemeAndPrimaryColor()
super.onCreate(savedInstanceState)

val binding: SimpleFrameLayoutMaterialBinding = SimpleFrameLayoutMaterialBinding.inflate(layoutInflater)
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/android/calendar/AllInOneActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
import com.android.calendar.settings.SettingsActivity;
import com.android.calendar.settings.SettingsActivityKt;
import com.android.calendar.settings.ViewDetailsPreferences;
import com.android.calendar.theme.DynamicThemeKt;
import com.android.calendarcommon2.Time;
import com.google.android.material.datepicker.CalendarConstraints;
import com.google.android.material.datepicker.MaterialDatePicker;
Expand Down Expand Up @@ -261,6 +262,7 @@ protected void onNewIntent(Intent intent) {

@Override
protected void onCreate(Bundle icicle) {
DynamicThemeKt.applyThemeAndPrimaryColor(this);
super.onCreate(icicle);

// This needs to be created before setContentView
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/android/calendar/EventInfoActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import androidx.fragment.app.FragmentTransaction;

import com.android.calendar.CalendarEventModel.ReminderEntry;
import com.android.calendar.theme.DynamicThemeKt;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -66,6 +67,7 @@ public void onChange(boolean selfChange) {

@Override
protected void onCreate(Bundle icicle) {
DynamicThemeKt.applyThemeAndPrimaryColor(this);
super.onCreate(icicle);

// Get the info needed for the fragment
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/android/calendar/SearchActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import com.android.calendar.CalendarController.EventType;
import com.android.calendar.CalendarController.ViewType;
import com.android.calendar.agenda.AgendaFragment;
import com.android.calendar.theme.DynamicThemeKt;
import com.android.calendarcommon2.Time;

import ws.xsoh.etar.R;
Expand Down Expand Up @@ -95,6 +96,7 @@ public void run() {

@Override
protected void onCreate(Bundle icicle) {
DynamicThemeKt.applyThemeAndPrimaryColor(this);
super.onCreate(icicle);
// This needs to be created before setContentView
mController = CalendarController.getInstance(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.android.calendar.CalendarEventModel.ReminderEntry;
import com.android.calendar.DynamicTheme;
import com.android.calendar.Utils;
import com.android.calendar.theme.DynamicThemeKt;
import com.android.calendarcommon2.Time;

import java.util.ArrayList;
Expand Down Expand Up @@ -64,6 +65,7 @@ public class EditEventActivity extends AbstractCalendarActivity {

@Override
protected void onCreate(Bundle icicle) {
DynamicThemeKt.applyThemeAndPrimaryColor(this);
super.onCreate(icicle);

mEventInfo = getEventInfoFromIntent(icicle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.android.calendar.theme.applyThemeAndPrimaryColor
import ws.xsoh.etar.R
import ws.xsoh.etar.databinding.SimpleFrameLayoutMaterialBinding

Expand All @@ -38,6 +39,7 @@ class SettingsActivity : AppCompatActivity(),
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {

override fun onCreate(savedInstanceState: Bundle?) {
applyThemeAndPrimaryColor()
super.onCreate(savedInstanceState)

val fragment = if (intent.hasExtra(EXTRA_SHOW_FRAGMENT)) {
Expand Down
86 changes: 86 additions & 0 deletions app/src/main/java/com/android/calendar/theme/DynamicTheme.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.android.calendar.theme

import android.app.UiModeManager
import android.content.Context
import android.content.res.Configuration
import android.graphics.Color
import android.os.Build
import android.util.TypedValue
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.graphics.ColorUtils
import androidx.core.view.WindowInsetsControllerCompat
import com.android.calendar.theme.ThemeUtils.isPureBlackModeEnabled
import com.android.calendar.theme.model.Theme
import ws.xsoh.etar.R

val AppCompatActivity.isSystemInDarkTheme: Boolean
get() = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES;

fun AppCompatActivity.applyThemeAndPrimaryColor() {
val selectedTheme = ThemeUtils.getTheme(this)
val selectedColor = ThemeUtils.getColor(this)

val uiModeManager = getSystemService(Context.UI_MODE_SERVICE) as UiModeManager

// Selected theme is system and dark mode is enabled with pure black mode
if (selectedTheme == Theme.SYSTEM && isPureBlackModeEnabled && isSystemInDarkTheme) {
theme.applyStyle(R.style.colorBackgroundBlack, true)
}

// Apply selected primary color to the theme
theme.applyStyle(selectedColor.resource, true)

// Set selected theme mode to the app
when (selectedTheme) {
Theme.SYSTEM -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_CUSTOM)
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
}

Theme.LIGHT -> {
setSystemBarConfiguration(light = true)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_NO)
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
}

else -> {
setSystemBarConfiguration(light = false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_YES)
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
}
}
}

private fun AppCompatActivity.setSystemBarConfiguration(light: Boolean) {
WindowInsetsControllerCompat(this.window, this.window.decorView.rootView).apply {
// Status bar color
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
isAppearanceLightStatusBars = light
} else {
window.statusBarColor = ColorUtils.setAlphaComponent(Color.BLACK, 120)
}

// Navigation bar color
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
isAppearanceLightNavigationBars = light
window.navigationBarColor = getStyledAttributeColor(android.R.attr.colorBackground)
}
}
}

private fun Context.getStyledAttributeColor(id: Int): Int {
val arr = obtainStyledAttributes(TypedValue().data, intArrayOf(id))
val styledAttr = arr.getColor(0, Color.WHITE)
arr.recycle()
return styledAttr
}
35 changes: 35 additions & 0 deletions app/src/main/java/com/android/calendar/theme/ThemeUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.android.calendar.theme

import android.content.Context
import android.os.Build
import com.android.calendar.Utils
import com.android.calendar.theme.model.Color
import com.android.calendar.theme.model.Theme

object ThemeUtils {

private const val THEME_PREF = "pref_theme"
private const val COLOR_PREF = "pref_color"
private const val PURE_BLACK_NIGHT_MODE = "pref_pure_black_night_mode"

val Context.isPureBlackModeEnabled: Boolean
get() = Utils.getSharedPreference(this, PURE_BLACK_NIGHT_MODE, false)

fun getTheme(context: Context): Theme {
val theme = Utils.getSharedPreference(
context,
THEME_PREF,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Theme.SYSTEM.name else Theme.LIGHT.name
)
return Theme.valueOf(theme.uppercase())
}

fun getColor(context: Context): Color {
val color = Utils.getSharedPreference(
context,
COLOR_PREF,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) Color.MONET.name else Color.TEAL.name
)
return Color.valueOf(color.uppercase())
}
}
14 changes: 14 additions & 0 deletions app/src/main/java/com/android/calendar/theme/model/Color.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.android.calendar.theme.model

import androidx.annotation.StyleRes
import ws.xsoh.etar.R

enum class Color(@StyleRes val resource: Int) {
MONET(R.style.colorAccentPrimaryDefault), // SYSTEM or DEFAULT
TEAL(R.style.colorAccentPrimaryTeal),
BLUE(R.style.colorAccentPrimaryBlue),
ORANGE(R.style.colorAccentPrimaryOrange),
GREEN(R.style.colorAccentPrimaryGreen),
RED(R.style.colorAccentPrimaryRed),
PURPLE(R.style.colorAccentPrimaryPurple)
}
8 changes: 8 additions & 0 deletions app/src/main/java/com/android/calendar/theme/model/Theme.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.android.calendar.theme.model

enum class Theme {
SYSTEM,
LIGHT,
DARK,
BLACK;
}
50 changes: 50 additions & 0 deletions app/src/main/res/values/styles-color.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>

<style name="colorBackgroundBlack">
<item name="android:colorBackground">@color/bg_black</item>
</style>

<style name="colorAccentPrimaryDefault">
<item name="colorAccent">@color/colorAccent</item>
<item name="colorPrimary">@color/colorAccent</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
</style>

<style name="colorAccentPrimaryTeal">
<item name="colorAccent">@color/colorAccent</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
</style>

<style name="colorAccentPrimaryBlue">
<item name="colorAccent">@color/colorBlueAccent</item>
<item name="colorPrimary">@color/colorBluePrimary</item>
<item name="colorPrimaryDark">@color/colorBluePrimaryDark</item>
</style>

<style name="colorAccentPrimaryOrange">
<item name="colorAccent">@color/colorOrangeAccent</item>
<item name="colorPrimary">@color/colorOrangePrimary</item>
<item name="colorPrimaryDark">@color/colorOrangePrimaryDark</item>
</style>

<style name="colorAccentPrimaryGreen">
<item name="colorAccent">@color/colorGreenAccent</item>
<item name="colorPrimary">@color/colorGreenPrimary</item>
<item name="colorPrimaryDark">@color/colorGreenPrimaryDark</item>
</style>

<style name="colorAccentPrimaryRed">
<item name="colorAccent">@color/colorRedAccent</item>
<item name="colorPrimary">@color/colorRedPrimary</item>
<item name="colorPrimaryDark">@color/colorRedPrimaryDark</item>
</style>

<style name="colorAccentPrimaryPurple">
<item name="colorAccent">@color/colorPurpleAccent</item>
<item name="colorPrimary">@color/colorPurplePrimary</item>
<item name="colorPrimaryDark">@color/colorPurplePrimaryDark</item>
</style>

</resources>

0 comments on commit 15b0433

Please sign in to comment.