From c34e9bd7b6e553324d419a01baa66ac4a1a9ffe0 Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Tue, 1 Jul 2025 20:40:03 +0200 Subject: [PATCH] Themes: use separate themes for DayNight/OLED/DynamicColors. Fixes #2123. --- src/main/AndroidManifest.xml | 3 +- .../opentracks/AbstractActivity.java | 4 +- .../de/dennisguse/opentracks/Startup.java | 8 +- .../opentracks/settings/PreferencesUtils.java | 78 +++++++++++++------ .../UserInterfaceSettingsFragment.java | 6 +- src/main/res/values-night/styles_theme.xml | 38 --------- src/main/res/values/settings.xml | 36 ++++++--- src/main/res/values/strings.xml | 6 +- src/main/res/values/styles_theme.xml | 55 ++++++++----- src/main/res/xml/settings_user_interface.xml | 10 +-- 10 files changed, 124 insertions(+), 120 deletions(-) delete mode 100644 src/main/res/values-night/styles_theme.xml diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index fe1887807..57e8fbb67 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -79,8 +79,7 @@ limitations under the License. android:hasFragileUserData="false" android:icon="@drawable/ic_launcher" android:label="@string/app_name" - android:supportsRtl="true" - android:theme="@style/OpenTracksTheme"> + android:supportsRtl="true"> format.getPreferenceId().equals(trackFileFormatName)) .findFirst().orElse(TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES); } @@ -715,30 +713,62 @@ public class PreferencesUtils { return getBoolean(R.string.import_prevent_reimport_key, defaultValue); } - /** - * @return * {@link androidx.appcompat.app.AppCompatDelegate}.MODE_* - * * 3: Night OLED friendly - */ - private static String getUiMode() { - final String defaultValue = getKey(R.string.night_mode_default); - final String value = getString(R.string.night_mode_key, defaultValue); - - return value; + record ThemeConfig(int themeResourceId, int dayNight, boolean dynamicColor) { } - public static boolean shouldApplyOledTheme() { - return resources.getString(R.string.night_mode_night_oled_value) - .equals(getUiMode()); + private static ThemeConfig getThemeMode() { + final String defaultValue = getKey(R.string.theme_default); + final String value = getString(R.string.theme_key, defaultValue); + + switch (value) { + case "0" -> { + return new ThemeConfig(R.style.DayNightColorTheme, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, false); + } + case "1" -> { + return new ThemeConfig(R.style.DayNightDynamicTheme, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, true); + } + case "2" -> { + return new ThemeConfig(R.style.DayNightColorTheme, AppCompatDelegate.MODE_NIGHT_NO, false); + } + case "3" -> { + return new ThemeConfig(R.style.DayNightDynamicTheme, AppCompatDelegate.MODE_NIGHT_NO, true); + } + case "4" -> { + return new ThemeConfig(R.style.DayNightColorTheme, AppCompatDelegate.MODE_NIGHT_YES, false); + } + case "5" -> { + return new ThemeConfig(R.style.DayNightDynamicTheme, AppCompatDelegate.MODE_NIGHT_YES, true); + } + case "6" -> { + return new ThemeConfig(R.style.NightOledColorTheme, AppCompatDelegate.MODE_NIGHT_YES, false); + } + case "7" -> { + return new ThemeConfig(R.style.NightOledDynamicTheme, AppCompatDelegate.MODE_NIGHT_YES, true); + } + + default -> { + return new ThemeConfig(R.style.DayNightColorTheme, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, false); + } + } + } + + public static void applyTheme(Context context) { + context.setTheme(getThemeMode().themeResourceId()); } public static void applyNightMode() { - String uiMode = getUiMode(); - if (resources.getString(R.string.night_mode_night_oled_value) - .equals(uiMode)) { - return; - } + ThemeConfig themeConfig = getThemeMode(); - AppCompatDelegate.setDefaultNightMode(Integer.parseInt(uiMode)); + AppCompatDelegate.setDefaultNightMode(themeConfig.dayNight); + } + + public static void applyNightModeAndDynamicColors(Application application) { + ThemeConfig themeConfig = getThemeMode(); + + applyNightMode(); + + if (application != null && themeConfig.dynamicColor) + DynamicColors.applyToActivitiesIfAvailable(application); } public static void resetPreferences(Context context, boolean readAgain) { diff --git a/src/main/java/de/dennisguse/opentracks/settings/UserInterfaceSettingsFragment.java b/src/main/java/de/dennisguse/opentracks/settings/UserInterfaceSettingsFragment.java index 3c8316801..b89de4cf7 100644 --- a/src/main/java/de/dennisguse/opentracks/settings/UserInterfaceSettingsFragment.java +++ b/src/main/java/de/dennisguse/opentracks/settings/UserInterfaceSettingsFragment.java @@ -2,7 +2,6 @@ package de.dennisguse.opentracks.settings; import android.content.Intent; import android.content.SharedPreferences; -import android.os.Build; import android.os.Bundle; import android.widget.Toast; @@ -15,7 +14,7 @@ import de.dennisguse.opentracks.R; public class UserInterfaceSettingsFragment extends PreferenceFragmentCompat { private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> { - if (PreferencesUtils.isKey(R.string.night_mode_key, key)) { + if (PreferencesUtils.isKey(R.string.theme_key, key)) { getActivity().runOnUiThread(() -> { PreferencesUtils.applyNightMode(); Toast.makeText(getContext(), R.string.settings_theme_switch_restart, Toast.LENGTH_LONG).show(); @@ -33,9 +32,6 @@ public class UserInterfaceSettingsFragment extends PreferenceFragmentCompat { startActivity(intent); return true; }); - - Preference dynamicColors = findPreference(getString(R.string.settings_ui_dynamic_colors_key)); - dynamicColors.setEnabled(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU); } @Override diff --git a/src/main/res/values-night/styles_theme.xml b/src/main/res/values-night/styles_theme.xml deleted file mode 100644 index 60c395697..000000000 --- a/src/main/res/values-night/styles_theme.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - diff --git a/src/main/res/values/settings.xml b/src/main/res/values/settings.xml index 98ff398cb..53e37a2ae 100644 --- a/src/main/res/values/settings.xml +++ b/src/main/res/values/settings.xml @@ -270,8 +270,7 @@ - uiDynamicColors - false + uiDynamicColors trackdetail_show_on_lockscreen_while_recording @@ -301,23 +300,36 @@ localeKey - nightMode - @string/night_mode_system_value - 1 - 2 - 3 - -1 + nightMode + @string/theme_daynight_value + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 - @string/night_mode_system_value - @string/night_mode_no_value - @string/night_mode_yes_value - @string/night_mode_night_oled_value + @string/theme_daynight_value + @string/theme_daynight_dynamic_value + @string/theme_day_value + @string/theme_day_dynamic_value + @string/theme_night_value + @string/theme_night_dynamic_value + @string/theme_oled_value + @string/theme_oled_dynamic_value + @string/settings_night_mode_option_system + @string/settings_night_mode_option_system_dynamic @string/settings_night_mode_option_day + @string/settings_night_mode_option_day_dynamic @string/settings_night_mode_option_night + @string/settings_night_mode_option_night_dynamic @string/settings_night_mode_option_night_oled + @string/settings_night_mode_option_night_oled_dynamic diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 2921d518e..cf82a6563 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -380,9 +380,13 @@ limitations under the License. System default UI Theme System + System (DynamicColor) Day + Day (DynamicColor) Night - Night (OLED friendly) + Night (DynamicColor) + OLED friendly + OLED friendly (DynamicColor) Time interval Lap length Average heart rate diff --git a/src/main/res/values/styles_theme.xml b/src/main/res/values/styles_theme.xml index 993669e1e..fb033d080 100644 --- a/src/main/res/values/styles_theme.xml +++ b/src/main/res/values/styles_theme.xml @@ -1,10 +1,7 @@ - - - - - - + + + + + + + + + diff --git a/src/main/res/xml/settings_user_interface.xml b/src/main/res/xml/settings_user_interface.xml index a037f0c0e..29f285843 100644 --- a/src/main/res/xml/settings_user_interface.xml +++ b/src/main/res/xml/settings_user_interface.xml @@ -11,19 +11,13 @@ app:useSimpleSummaryProvider="true" /> - -