Themes: use separate themes for DayNight/OLED/DynamicColors.

Fixes #2123.
This commit is contained in:
Dennis Guse
2025-07-01 20:40:03 +02:00
parent edac784b1e
commit c34e9bd7b6
10 changed files with 124 additions and 120 deletions
@@ -37,9 +37,7 @@ public abstract class AbstractActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
if (PreferencesUtils.shouldApplyOledTheme()) {
setTheme(R.style.OpenTracksThemeOled);
}
PreferencesUtils.applyTheme(this);
EdgeToEdge.enable(this);
@@ -6,8 +6,6 @@ import android.content.Context;
import android.os.Build;
import android.util.Log;
import com.google.android.material.color.DynamicColors;
import java.lang.reflect.Method;
import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -34,11 +32,7 @@ public class Startup extends Application {
// Set default values of preferences on first start.
PreferencesUtils.resetPreferences(this, false);
PreferencesUtils.applyDefaultUnit();
PreferencesUtils.applyNightMode();
if (PreferencesUtils.shouldUseDynamicColors()) {
DynamicColors.applyToActivitiesIfAvailable(this);
}
PreferencesUtils.applyNightModeAndDynamicColors(this);
}
@Override
@@ -17,6 +17,7 @@
package de.dennisguse.opentracks.settings;
import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
@@ -30,6 +31,8 @@ import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.preference.PreferenceManager;
import com.google.android.material.color.DynamicColors;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
@@ -338,11 +341,6 @@ public class PreferencesUtils {
return getBoolean(R.string.chart_display_heart_rate_key, DEFAULT);
}
public static boolean shouldUseDynamicColors() {
final boolean DEFAULT = resources.getBoolean(R.bool.settings_ui_dynamic_colors_default);
return getBoolean(R.string.settings_ui_dynamic_colors_key, DEFAULT);
}
public static boolean shouldVoiceAnnouncementOnDeviceSpeaker() {
final boolean DEFAULT = resources.getBoolean(R.bool.voice_on_device_speaker_default);
return getBoolean(R.string.voice_on_device_speaker_key, DEFAULT);
@@ -705,7 +703,7 @@ public class PreferencesUtils {
public static TrackFileFormat getExportTrackFileFormat() {
final String TRACKFILEFORMAT_NAME_DEFAULT = getString(R.string.export_trackfileformat_default, null);
String trackFileFormatName = getString(R.string.export_trackfileformat_key, TRACKFILEFORMAT_NAME_DEFAULT);
return Arrays.stream(TrackFileFormat.values())
return Arrays.stream(TrackFileFormat.values())
.filter(format -> 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) {
@@ -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