[android][sdk] Fix ThemeUtils usage in sdk

Signed-off-by: Andrei Shkrob <github@shkrob.dev>
This commit is contained in:
Andrei Shkrob
2025-08-08 17:48:12 +02:00
committed by Konstantin Pastbin
parent 886d569895
commit 447266c328
23 changed files with 162 additions and 190 deletions

View File

@@ -458,12 +458,10 @@ public class MwmActivity extends BaseMwmFragmentActivity
@StyleRes @StyleRes
protected int getThemeResourceId(@NonNull String theme) protected int getThemeResourceId(@NonNull String theme)
{ {
Context context = getApplicationContext(); if (Config.UiTheme.isDefault(theme))
if (ThemeUtils.isDefaultTheme(context, theme))
return R.style.MwmTheme_MainActivity; return R.style.MwmTheme_MainActivity;
if (ThemeUtils.isNightTheme(context, theme)) if (Config.UiTheme.isNight(theme))
return R.style.MwmTheme_Night_MainActivity; return R.style.MwmTheme_Night_MainActivity;
return super.getThemeResourceId(theme); return super.getThemeResourceId(theme);
@@ -585,7 +583,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void refreshLightStatusBar() private void refreshLightStatusBar()
{ {
UiUtils.setLightStatusBar(this, !(ThemeUtils.isNightTheme(this) || RoutingController.get().isPlanning() UiUtils.setLightStatusBar(this, !(ThemeUtils.isNightTheme() || RoutingController.get().isPlanning()
|| ChoosePositionMode.get() != ChoosePositionMode.None)); || ChoosePositionMode.get() != ChoosePositionMode.None));
} }

View File

@@ -60,11 +60,10 @@ public class SplashActivity extends AppCompatActivity
{ {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final Context context = getApplicationContext(); final String theme = Config.UiTheme.getCurrent();
final String theme = Config.getCurrentUiTheme(context); if (Config.UiTheme.isDefault(theme))
if (ThemeUtils.isDefaultTheme(context, theme))
setTheme(R.style.MwmTheme_Splash); setTheme(R.style.MwmTheme_Splash);
else if (ThemeUtils.isNightTheme(context, theme)) else if (Config.UiTheme.isNight(theme))
setTheme(R.style.MwmTheme_Night_Splash); setTheme(R.style.MwmTheme_Night_Splash);
else else
throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme); throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme);

View File

@@ -15,7 +15,7 @@ public class BaseMwmDialogFragment extends DialogFragment
@StyleRes @StyleRes
protected final int getFullscreenTheme() protected final int getFullscreenTheme()
{ {
return ThemeUtils.isNightTheme(requireContext()) ? getFullscreenDarkTheme() : getFullscreenLightTheme(); return ThemeUtils.isNightTheme() ? getFullscreenDarkTheme() : getFullscreenLightTheme();
} }
protected int getStyle() protected int getStyle()

View File

@@ -1,7 +1,6 @@
package app.organicmaps.base; package app.organicmaps.base;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color; import android.graphics.Color;
import android.media.AudioManager; import android.media.AudioManager;
@@ -24,7 +23,6 @@ import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.concurrency.UiThread; import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.util.RtlUtils; import app.organicmaps.util.RtlUtils;
import app.organicmaps.util.ThemeUtils;
import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.appbar.MaterialToolbar;
import java.util.Objects; import java.util.Objects;
@@ -40,12 +38,10 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
@StyleRes @StyleRes
protected int getThemeResourceId(@NonNull String theme) protected int getThemeResourceId(@NonNull String theme)
{ {
Context context = getApplicationContext(); if (Config.UiTheme.isDefault(theme))
if (ThemeUtils.isDefaultTheme(context, theme))
return R.style.MwmTheme; return R.style.MwmTheme;
if (ThemeUtils.isNightTheme(context, theme)) if (Config.UiTheme.isNight(theme))
return R.style.MwmTheme_Night; return R.style.MwmTheme_Night;
throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme); throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme);
@@ -62,7 +58,7 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
protected final void onCreate(@Nullable Bundle savedInstanceState) protected final void onCreate(@Nullable Bundle savedInstanceState)
{ {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mThemeName = Config.getCurrentUiTheme(getApplicationContext()); mThemeName = Config.UiTheme.getCurrent();
setTheme(getThemeResourceId(mThemeName)); setTheme(getThemeResourceId(mThemeName));
EdgeToEdge.enable(this, SystemBarStyle.dark(Color.TRANSPARENT)); EdgeToEdge.enable(this, SystemBarStyle.dark(Color.TRANSPARENT));
RtlUtils.manageRtl(this); RtlUtils.manageRtl(this);
@@ -122,7 +118,7 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
public void onPostResume() public void onPostResume()
{ {
super.onPostResume(); super.onPostResume();
if (!mThemeName.equals(Config.getCurrentUiTheme(getApplicationContext()))) if (!mThemeName.equals(Config.UiTheme.getCurrent()))
{ {
// Workaround described in https://code.google.com/p/android/issues/detail?id=93731 // Workaround described in https://code.google.com/p/android/issues/detail?id=93731
UiThread.runLater(this::recreate); UiThread.runLater(this::recreate);

View File

@@ -42,7 +42,7 @@ public class BookmarkCategoriesActivity extends BaseToolbarActivity
@StyleRes @StyleRes
public int getThemeResourceId(@NonNull String theme) public int getThemeResourceId(@NonNull String theme)
{ {
return ThemeUtils.getWindowBgThemeResourceId(getApplicationContext(), theme); return ThemeUtils.getWindowBgThemeResourceId(theme);
} }
@Override @Override

View File

@@ -41,7 +41,7 @@ public class BookmarkListActivity extends BaseToolbarActivity
@StyleRes @StyleRes
public int getThemeResourceId(@NonNull String theme) public int getThemeResourceId(@NonNull String theme)
{ {
return ThemeUtils.getCardBgThemeResourceId(getApplicationContext(), theme); return ThemeUtils.getCardBgThemeResourceId(theme);
} }
@Override @Override

View File

@@ -10,19 +10,20 @@ import androidx.car.app.CarContext;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.MapStyle; import app.organicmaps.sdk.MapStyle;
import app.organicmaps.sdk.routing.RoutingController; import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.util.Config;
public final class ThemeUtils public final class ThemeUtils
{ {
public enum ThemeMode public enum ThemeMode
{ {
AUTO(R.string.auto, R.string.theme_auto), AUTO(R.string.auto, Config.UiTheme.AUTO),
LIGHT(R.string.off, R.string.theme_default), LIGHT(R.string.off, Config.UiTheme.DEFAULT),
NIGHT(R.string.on, R.string.theme_night); NIGHT(R.string.on, Config.UiTheme.NIGHT);
ThemeMode(@StringRes int titleId, @StringRes int prefsKeyId) ThemeMode(@StringRes int titleId, @NonNull String config)
{ {
mTitleId = titleId; mTitleId = titleId;
mPrefsKeyId = prefsKeyId; mConfig = config;
} }
@StringRes @StringRes
@@ -31,16 +32,16 @@ public final class ThemeUtils
return mTitleId; return mTitleId;
} }
@StringRes @NonNull
public int getPrefsKeyId() public String getConfig()
{ {
return mPrefsKeyId; return mConfig;
} }
@StringRes @StringRes
private final int mTitleId; private final int mTitleId;
@StringRes @NonNull
private final int mPrefsKeyId; private final String mConfig;
} }
private static final String ANDROID_AUTO_PREFERENCES_FILE_KEY = "ANDROID_AUTO_PREFERENCES_FILE_KEY"; private static final String ANDROID_AUTO_PREFERENCES_FILE_KEY = "ANDROID_AUTO_PREFERENCES_FILE_KEY";
@@ -79,23 +80,20 @@ public final class ThemeUtils
@UiThread @UiThread
public static void setThemeMode(@NonNull CarContext context, @NonNull ThemeMode themeMode) public static void setThemeMode(@NonNull CarContext context, @NonNull ThemeMode themeMode)
{ {
getSharedPreferences(context).edit().putString(THEME_KEY, context.getString(themeMode.getPrefsKeyId())).commit(); getSharedPreferences(context).edit().putString(THEME_KEY, themeMode.getConfig()).commit();
update(context, themeMode); update(context, themeMode);
} }
@NonNull @NonNull
public static ThemeMode getThemeMode(@NonNull CarContext context) public static ThemeMode getThemeMode(@NonNull CarContext context)
{ {
final String autoTheme = context.getString(R.string.theme_auto); final String themeMode = getSharedPreferences(context).getString(THEME_KEY, ThemeMode.AUTO.getConfig());
final String lightTheme = context.getString(R.string.theme_default);
final String nightTheme = context.getString(R.string.theme_night);
final String themeMode = getSharedPreferences(context).getString(THEME_KEY, autoTheme);
if (themeMode.equals(autoTheme)) if (themeMode.equals(ThemeMode.AUTO.getConfig()))
return ThemeMode.AUTO; return ThemeMode.AUTO;
else if (themeMode.equals(lightTheme)) else if (themeMode.equals(ThemeMode.LIGHT.getConfig()))
return ThemeMode.LIGHT; return ThemeMode.LIGHT;
else if (themeMode.equals(nightTheme)) else if (themeMode.equals(ThemeMode.NIGHT.getConfig()))
return ThemeMode.NIGHT; return ThemeMode.NIGHT;
else else
throw new IllegalArgumentException("Unsupported value"); throw new IllegalArgumentException("Unsupported value");

View File

@@ -79,8 +79,8 @@ public class HoursMinutesPickerFragment extends BaseMwmDialogFragment
mTabs.getTabAt(mSelectedTab).select(); mTabs.getTabAt(mSelectedTab).select();
@StyleRes @StyleRes
final int theme = ThemeUtils.isNightTheme(requireContext()) ? R.style.MwmMain_DialogFragment_TimePicker_Night final int theme = ThemeUtils.isNightTheme() ? R.style.MwmMain_DialogFragment_TimePicker_Night
: R.style.MwmMain_DialogFragment_TimePicker; : R.style.MwmMain_DialogFragment_TimePicker;
final AlertDialog dialog = new MaterialAlertDialogBuilder(requireActivity(), theme) final AlertDialog dialog = new MaterialAlertDialogBuilder(requireActivity(), theme)
.setView(root) .setView(root)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
@@ -141,8 +141,8 @@ public class HoursMinutesPickerFragment extends BaseMwmDialogFragment
MaterialTextView tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false); MaterialTextView tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);
tabView.setText(getResources().getString(R.string.editor_time_from)); tabView.setText(getResources().getString(R.string.editor_time_from));
final ColorStateList textColor = AppCompatResources.getColorStateList( final ColorStateList textColor = AppCompatResources.getColorStateList(
requireContext(), ThemeUtils.isNightTheme(requireContext()) ? R.color.accent_color_selector_night requireContext(),
: R.color.accent_color_selector); ThemeUtils.isNightTheme() ? R.color.accent_color_selector_night : R.color.accent_color_selector);
tabView.setTextColor(textColor); tabView.setTextColor(textColor);
mTabs.addTab(mTabs.newTab().setCustomView(tabView), true); mTabs.addTab(mTabs.newTab().setCustomView(tabView), true);
tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false); tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);

View File

@@ -214,7 +214,7 @@ public class MapButtonsController extends Fragment
// helpButton.setImageResource(R.drawable.ic_launcher); // helpButton.setImageResource(R.drawable.ic_launcher);
// } // }
// // Keep this button colorful in normal theme. // // Keep this button colorful in normal theme.
// if (!ThemeUtils.isNightTheme(requireContext())) // if (!ThemeUtils.isNightTheme())
// helpButton.getDrawable().setTintList(null); // helpButton.getDrawable().setTintList(null);
} }
else if (leftButtonView != null) else if (leftButtonView != null)

View File

@@ -43,22 +43,20 @@ public class TrafficButton
void turnOff() void turnOff()
{ {
stopWaitingAnimation(); stopWaitingAnimation();
mButton.setImageResource(ThemeUtils.isNightTheme(mButton.getContext()) ? R.drawable.ic_traffic_on_night mButton.setImageResource(ThemeUtils.isNightTheme() ? R.drawable.ic_traffic_on_night : R.drawable.ic_traffic_on);
: R.drawable.ic_traffic_on);
} }
void turnOn() void turnOn()
{ {
stopWaitingAnimation(); stopWaitingAnimation();
mButton.setImageResource(ThemeUtils.isNightTheme(mButton.getContext()) ? R.drawable.ic_traffic_on_night mButton.setImageResource(ThemeUtils.isNightTheme() ? R.drawable.ic_traffic_on_night : R.drawable.ic_traffic_on);
: R.drawable.ic_traffic_on);
} }
void markAsOutdated() void markAsOutdated()
{ {
stopWaitingAnimation(); stopWaitingAnimation();
mButton.setImageResource(ThemeUtils.isNightTheme(mButton.getContext()) ? R.drawable.ic_traffic_outdated_night mButton.setImageResource(ThemeUtils.isNightTheme() ? R.drawable.ic_traffic_outdated_night
: R.drawable.ic_traffic_outdated); : R.drawable.ic_traffic_outdated);
} }
void startWaitingAnimation() void startWaitingAnimation()

View File

@@ -90,7 +90,7 @@ public class TransitStepView extends View implements MultilineLayoutManager.Sque
{ {
mDrawable = null; mDrawable = null;
mText = info.getDistance() + " " + info.getDistanceUnits(); mText = info.getDistance() + " " + info.getDistanceUnits();
mTextPaint.setColor(ThemeUtils.isDefaultTheme(getContext()) ? Color.BLACK : Color.WHITE); mTextPaint.setColor(ThemeUtils.isDefaultTheme() ? Color.BLACK : Color.WHITE);
} }
else else
{ {

View File

@@ -148,7 +148,7 @@ public final class Map
{ {
assert mLocationHelper != null : "LocationHelper must be initialized before calling onSurfaceCreated"; assert mLocationHelper != null : "LocationHelper must be initialized before calling onSurfaceCreated";
if (isThemeChangingProcess(context)) if (isThemeChangingProcess())
{ {
Logger.d(TAG, "Theme changing process, skip 'onSurfaceCreated' callback"); Logger.d(TAG, "Theme changing process, skip 'onSurfaceCreated' callback");
return; return;
@@ -203,7 +203,7 @@ public final class Map
public void onSurfaceChanged(final Context context, final Surface surface, Rect surfaceFrame, public void onSurfaceChanged(final Context context, final Surface surface, Rect surfaceFrame,
boolean isSurfaceCreating) boolean isSurfaceCreating)
{ {
if (isThemeChangingProcess(context)) if (isThemeChangingProcess())
{ {
Logger.d(TAG, "Theme changing process, skip 'onSurfaceChanged' callback"); Logger.d(TAG, "Theme changing process, skip 'onSurfaceChanged' callback");
return; return;
@@ -265,7 +265,7 @@ public final class Map
public void onPause(final Context context) public void onPause(final Context context)
{ {
mUiThemeOnPause = Config.getCurrentUiTheme(context); mUiThemeOnPause = Config.UiTheme.getCurrent();
// Pause/Resume can be called without surface creation/destroy. // Pause/Resume can be called without surface creation/destroy.
if (mSurfaceAttached) if (mSurfaceAttached)
@@ -370,9 +370,9 @@ public final class Map
nativeApplyWidgets(); nativeApplyWidgets();
} }
private boolean isThemeChangingProcess(final Context context) private boolean isThemeChangingProcess()
{ {
return mUiThemeOnPause != null && !mUiThemeOnPause.equals(Config.getCurrentUiTheme(context)); return mUiThemeOnPause != null && !mUiThemeOnPause.equals(Config.UiTheme.getCurrent());
} }
// Engine // Engine

View File

@@ -7,7 +7,6 @@ import androidx.annotation.NonNull;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import app.organicmaps.BuildConfig; import app.organicmaps.BuildConfig;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.util.ThemeUtils;
public final class Config public final class Config
{ {
@@ -24,8 +23,6 @@ public final class Config
private static final String KEY_MISC_DISCLAIMER_ACCEPTED = "IsDisclaimerApproved"; private static final String KEY_MISC_DISCLAIMER_ACCEPTED = "IsDisclaimerApproved";
private static final String KEY_MISC_LOCATION_REQUESTED = "LocationRequested"; private static final String KEY_MISC_LOCATION_REQUESTED = "LocationRequested";
private static final String KEY_MISC_UI_THEME = "UiTheme";
private static final String KEY_MISC_UI_THEME_SETTINGS = "UiThemeSettings";
private static final String KEY_MISC_USE_MOBILE_DATA = "UseMobileData"; private static final String KEY_MISC_USE_MOBILE_DATA = "UseMobileData";
private static final String KEY_MISC_USE_MOBILE_DATA_TIMESTAMP = "UseMobileDataTimestamp"; private static final String KEY_MISC_USE_MOBILE_DATA_TIMESTAMP = "UseMobileDataTimestamp";
private static final String KEY_MISC_USE_MOBILE_DATA_ROAMING = "UseMobileDataRoaming"; private static final String KEY_MISC_USE_MOBILE_DATA_ROAMING = "UseMobileDataRoaming";
@@ -218,47 +215,77 @@ public final class Config
setBool(KEY_MISC_LOCATION_REQUESTED); setBool(KEY_MISC_LOCATION_REQUESTED);
} }
@NonNull public static class UiTheme
public static String getCurrentUiTheme(@NonNull Context context)
{ {
// This is the actual map theme, only set to theme_default/night private static final String KEY_UI_THEME = "UiTheme";
final String defaultTheme = context.getString(R.string.theme_default); private static final String KEY_UI_THEME_SETTINGS = "UiThemeSettings";
final String res = getString(KEY_MISC_UI_THEME, defaultTheme);
if (ThemeUtils.isValidTheme(context, res)) public static final String AUTO = "auto";
return res; public static final String NIGHT = "night";
public static final String NAV_AUTO = "nav_auto";
public static final String DEFAULT = "default";
return defaultTheme; public static boolean isAuto(@NonNull String theme)
} {
return AUTO.equals(theme);
}
public static void setCurrentUiTheme(@NonNull Context context, @NonNull String theme) public static boolean isNavAuto(@NonNull String theme)
{ {
if (getCurrentUiTheme(context).equals(theme)) return NAV_AUTO.equals(theme);
return; }
setString(KEY_MISC_UI_THEME, theme); public static boolean isNight(@NonNull String theme)
} {
return NIGHT.equals(theme);
}
@NonNull public static boolean isDefault(@NonNull String theme)
public static String getUiThemeSettings(@NonNull Context context) {
{ return DEFAULT.equals(theme);
// This is the default theme *mode*, eg. auto/dark/nav_auto/light. }
final String defaultSetting = context.getString(R.string.theme_nav_auto);
final String res = getString(KEY_MISC_UI_THEME_SETTINGS, defaultSetting);
if (ThemeUtils.isValidTheme(context, res) || ThemeUtils.isAutoTheme(context, res)
|| ThemeUtils.isNavAutoTheme(context, res))
return res;
return defaultSetting; @NonNull
} public static String getCurrent()
{
final String res = getString(KEY_UI_THEME, DEFAULT);
if (isValid(res))
return res;
public static boolean setUiThemeSettings(@NonNull Context context, String theme) return DEFAULT;
{ }
if (getUiThemeSettings(context).equals(theme))
return false;
setString(KEY_MISC_UI_THEME_SETTINGS, theme); public static void setCurrent(@NonNull String theme)
return true; {
if (getCurrent().equals(theme))
return;
setString(KEY_UI_THEME, theme);
}
@NonNull
public static String getUiThemeSettings()
{
final String res = getString(KEY_UI_THEME_SETTINGS, DEFAULT);
if (isValid(res) || isAuto(res) || isNavAuto(res))
return res;
return DEFAULT;
}
public static boolean setUiThemeSettings(String theme)
{
if (getUiThemeSettings().equals(theme))
return false;
setString(KEY_UI_THEME_SETTINGS, theme);
return true;
}
private static boolean isValid(@NonNull String theme)
{
return DEFAULT.equals(theme) || NIGHT.equals(theme);
}
} }
public static boolean isLargeFontsSize() public static boolean isLargeFontsSize()

View File

@@ -89,7 +89,7 @@ class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ViewHolde
@DrawableRes @DrawableRes
private static int getDrawableResIdByKey(@NonNull Context context, @NonNull String packageName, @NonNull String key) private static int getDrawableResIdByKey(@NonNull Context context, @NonNull String packageName, @NonNull String key)
{ {
final boolean isNightTheme = ThemeUtils.isNightTheme(context); final boolean isNightTheme = ThemeUtils.isNightTheme();
String iconId = "ic_" + key; String iconId = "ic_" + key;
if (isNightTheme) if (isNightTheme)
iconId = iconId + "_night"; iconId = iconId + "_night";

View File

@@ -37,7 +37,7 @@ public class SearchActivity extends BaseMwmFragmentActivity
@StyleRes @StyleRes
public int getThemeResourceId(@NonNull String theme) public int getThemeResourceId(@NonNull String theme)
{ {
return ThemeUtils.getCardBgThemeResourceId(getApplicationContext(), theme); return ThemeUtils.getCardBgThemeResourceId(theme);
} }
@Override @Override

View File

@@ -47,7 +47,7 @@ abstract class BaseXmlSettingsFragment extends PreferenceFragmentCompat
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
int color; int color;
if (ThemeUtils.isDefaultTheme(requireContext())) if (ThemeUtils.isDefaultTheme())
color = ContextCompat.getColor(requireContext(), R.color.bg_cards); color = ContextCompat.getColor(requireContext(), R.color.bg_cards);
else else
color = ContextCompat.getColor(requireContext(), R.color.bg_cards_night); color = ContextCompat.getColor(requireContext(), R.color.bg_cards_night);

View File

@@ -3,13 +3,11 @@ package app.organicmaps.settings;
import static app.organicmaps.leftbutton.LeftButtonsHolder.DISABLE_BUTTON_CODE; import static app.organicmaps.leftbutton.LeftButtonsHolder.DISABLE_BUTTON_CODE;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceCategory;
@@ -441,19 +439,19 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
private void initMapStylePrefsCallbacks() private void initMapStylePrefsCallbacks()
{ {
final ListPreference pref = getPreference(getString(R.string.pref_map_style)); final ListPreference pref = getPreference(getString(R.string.pref_map_style));
pref.setEntryValues(new CharSequence[] {Config.UiTheme.DEFAULT, Config.UiTheme.NIGHT, Config.UiTheme.AUTO,
String curTheme = Config.getUiThemeSettings(requireContext()); Config.UiTheme.NAV_AUTO});
pref.setValue(curTheme); pref.setValue(Config.UiTheme.getUiThemeSettings());
pref.setSummary(pref.getEntry()); pref.setSummary(pref.getEntry());
pref.setOnPreferenceChangeListener((preference, newValue) -> { pref.setOnPreferenceChangeListener((preference, newValue) -> {
final String themeName = (String) newValue; final String themeName = (String) newValue;
if (!Config.setUiThemeSettings(requireContext(), themeName)) if (!Config.UiTheme.setUiThemeSettings(themeName))
return true; return true;
ThemeSwitcher.INSTANCE.restart(false); ThemeSwitcher.INSTANCE.restart(false);
ThemeMode mode = ThemeMode.getInstance(requireContext().getApplicationContext(), themeName); final ThemeMode mode = ThemeMode.getInstance(themeName);
CharSequence summary = pref.getEntries()[mode.ordinal()]; final CharSequence summary = pref.getEntries()[mode.ordinal()];
pref.setSummary(summary); pref.setSummary(summary);
return true; return true;
}); });
@@ -552,24 +550,25 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
enum ThemeMode enum ThemeMode
{ {
DEFAULT(R.string.theme_default), DEFAULT(Config.UiTheme.DEFAULT),
NIGHT(R.string.theme_night), NIGHT(Config.UiTheme.NIGHT),
AUTO(R.string.theme_auto), AUTO(Config.UiTheme.AUTO),
NAV_AUTO(R.string.theme_nav_auto); NAV_AUTO(Config.UiTheme.NAV_AUTO);
private final int mModeStringId; @NonNull
private final String mMode;
ThemeMode(@StringRes int modeStringId) ThemeMode(@NonNull String mode)
{ {
mModeStringId = modeStringId; mMode = mode;
} }
@NonNull @NonNull
public static ThemeMode getInstance(@NonNull Context context, @NonNull String src) public static ThemeMode getInstance(@NonNull String src)
{ {
for (ThemeMode each : values()) for (ThemeMode each : values())
{ {
if (context.getResources().getString(each.mModeStringId).equals(src)) if (each.mMode.equals(src))
return each; return each;
} }
return AUTO; return AUTO;

View File

@@ -8,7 +8,6 @@ import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.app.AppCompatDelegate;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.downloader.DownloaderStatusIcon; import app.organicmaps.downloader.DownloaderStatusIcon;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.MapStyle; import app.organicmaps.sdk.MapStyle;
@@ -28,17 +27,23 @@ public enum ThemeSwitcher
@Override @Override
public void run() public void run()
{ {
boolean isNavAuto = RoutingController.get().isNavigating() && ThemeUtils.isNavAutoTheme(mContext); boolean navAuto = RoutingController.get().isNavigating() && ThemeUtils.isNavAutoTheme();
// Cancel old checker // Cancel old checker
UiThread.cancelDelayedTasks(mAutoThemeChecker); UiThread.cancelDelayedTasks(mAutoThemeChecker);
if (isNavAuto || ThemeUtils.isAutoTheme(mContext)) String theme;
if (navAuto || ThemeUtils.isAutoTheme())
{ {
UiThread.runLater(mAutoThemeChecker, CHECK_INTERVAL_MS); UiThread.runLater(mAutoThemeChecker, CHECK_INTERVAL_MS);
setThemeAndMapStyle(calcAutoTheme()); theme = calcAutoTheme();
} }
else // Only reached when an auto mode should be light else
setThemeAndMapStyle(mContext.getResources().getString(R.string.theme_default)); {
// Happens when exiting the Navigation mode. Should restore the light.
theme = Config.UiTheme.DEFAULT;
}
setThemeAndMapStyle(theme);
} }
}; };
@@ -64,8 +69,8 @@ public enum ThemeSwitcher
public void restart(boolean isRendererActive) public void restart(boolean isRendererActive)
{ {
mRendererActive = isRendererActive; mRendererActive = isRendererActive;
String theme = Config.getUiThemeSettings(mContext); String theme = Config.UiTheme.getUiThemeSettings();
if (ThemeUtils.isAutoTheme(mContext, theme) || ThemeUtils.isNavAutoTheme(mContext, theme)) if (ThemeUtils.isAutoTheme() || ThemeUtils.isNavAutoTheme())
{ {
mAutoThemeChecker.run(); mAutoThemeChecker.run();
return; return;
@@ -78,10 +83,10 @@ public enum ThemeSwitcher
private void setThemeAndMapStyle(@NonNull String theme) private void setThemeAndMapStyle(@NonNull String theme)
{ {
UiModeManager uiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE); UiModeManager uiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
String oldTheme = Config.getCurrentUiTheme(mContext); String oldTheme = Config.UiTheme.getCurrent();
MapStyle style; MapStyle style;
if (ThemeUtils.isNightTheme(mContext, theme)) if (ThemeUtils.isNightTheme())
{ {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_YES); uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_YES);
@@ -112,7 +117,7 @@ public enum ThemeSwitcher
if (!theme.equals(oldTheme)) if (!theme.equals(oldTheme))
{ {
Config.setCurrentUiTheme(mContext, theme); Config.UiTheme.setCurrent(theme);
DownloaderStatusIcon.clearCache(); DownloaderStatusIcon.clearCache();
final Activity a = MwmApplication.from(mContext).getTopActivity(); final Activity a = MwmApplication.from(mContext).getTopActivity();
@@ -152,9 +157,7 @@ public enum ThemeSwitcher
@NonNull @NonNull
private String calcAutoTheme() private String calcAutoTheme()
{ {
String defaultTheme = mContext.getResources().getString(R.string.theme_default); final Location last = MwmApplication.from(mContext).getLocationHelper().getSavedLocation();
String nightTheme = mContext.getResources().getString(R.string.theme_night);
Location last = MwmApplication.from(mContext).getLocationHelper().getSavedLocation();
boolean day; boolean day;
if (last != null) if (last != null)
@@ -168,6 +171,6 @@ public enum ThemeSwitcher
day = (currentHour < 18 && currentHour > 6); day = (currentHour < 18 && currentHour > 6);
} }
return (day ? defaultTheme : nightTheme); return (day ? Config.UiTheme.DEFAULT : Config.UiTheme.NIGHT);
} }
} }

View File

@@ -16,7 +16,8 @@ public final class ThemeUtils
private ThemeUtils() {} private ThemeUtils() {}
public static @ColorInt int getColor(@NonNull Context context, @AttrRes int attr) @ColorInt
public static int getColor(@NonNull Context context, @AttrRes int attr)
{ {
if (!context.getTheme().resolveAttribute(attr, VALUE_BUFFER, true)) if (!context.getTheme().resolveAttribute(attr, VALUE_BUFFER, true))
throw new IllegalArgumentException("Failed to resolve color theme attribute"); throw new IllegalArgumentException("Failed to resolve color theme attribute");
@@ -44,76 +45,45 @@ public final class ThemeUtils
return VALUE_BUFFER.resourceId; return VALUE_BUFFER.resourceId;
} }
public static boolean isDefaultTheme(@NonNull Context context) public static boolean isDefaultTheme()
{ {
return isDefaultTheme(context, Config.getCurrentUiTheme(context)); return Config.UiTheme.isDefault(Config.UiTheme.getCurrent());
} }
public static boolean isDefaultTheme(@NonNull Context context, String theme) public static boolean isNightTheme()
{ {
String defaultTheme = context.getString(R.string.theme_default); return Config.UiTheme.isNight(Config.UiTheme.getCurrent());
return defaultTheme.equals(theme);
} }
public static boolean isNightTheme(@NonNull Context context) public static boolean isAutoTheme()
{ {
return isNightTheme(context, Config.getCurrentUiTheme(context)); return Config.UiTheme.isAuto(Config.UiTheme.getUiThemeSettings());
} }
public static boolean isNightTheme(@NonNull Context context, String theme) public static boolean isNavAutoTheme()
{ {
String nightTheme = context.getString(R.string.theme_night); return Config.UiTheme.isNavAuto(Config.UiTheme.getUiThemeSettings());
return nightTheme.equals(theme);
}
public static boolean isAutoTheme(@NonNull Context context)
{
return isAutoTheme(context, Config.getUiThemeSettings(context));
}
public static boolean isAutoTheme(@NonNull Context context, String theme)
{
String autoTheme = context.getString(R.string.theme_auto);
return autoTheme.equals(theme);
}
public static boolean isNavAutoTheme(@NonNull Context context)
{
return isNavAutoTheme(context, Config.getUiThemeSettings(context));
}
public static boolean isNavAutoTheme(@NonNull Context context, String theme)
{
String navAutoTheme = context.getString(R.string.theme_nav_auto);
return navAutoTheme.equals(theme);
}
public static boolean isValidTheme(@NonNull Context context, String theme)
{
String defaultTheme = context.getString(R.string.theme_default);
String nightTheme = context.getString(R.string.theme_night);
return (defaultTheme.equals(theme) || nightTheme.equals(theme));
} }
@StyleRes @StyleRes
public static int getCardBgThemeResourceId(@NonNull Context context, @NonNull String theme) public static int getCardBgThemeResourceId(@NonNull String theme)
{ {
if (isDefaultTheme(context, theme)) if (Config.UiTheme.isDefault(theme))
return R.style.MwmTheme_CardBg; return R.style.MwmTheme_CardBg;
if (isNightTheme(context, theme)) if (Config.UiTheme.isNight(theme))
return R.style.MwmTheme_Night_CardBg; return R.style.MwmTheme_Night_CardBg;
throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme); throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme);
} }
@StyleRes @StyleRes
public static int getWindowBgThemeResourceId(@NonNull Context context, @NonNull String theme) public static int getWindowBgThemeResourceId(@NonNull String theme)
{ {
if (isDefaultTheme(context, theme)) if (Config.UiTheme.isDefault(theme))
return R.style.MwmTheme_WindowBg; return R.style.MwmTheme_WindowBg;
if (isNightTheme(context, theme)) if (Config.UiTheme.isNight(theme))
return R.style.MwmTheme_Night_WindowBg; return R.style.MwmTheme_Night_WindowBg;
throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme); throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme);

View File

@@ -35,10 +35,9 @@ public class RoutingToolbarButton extends AppCompatRadioButton
private void initView() private void initView()
{ {
setBackgroundResource(ThemeUtils.isNightTheme(getContext()) ? R.drawable.routing_toolbar_button_night final boolean isNightTheme = ThemeUtils.isNightTheme();
: R.drawable.routing_toolbar_button); setBackgroundResource(isNightTheme ? R.drawable.routing_toolbar_button_night : R.drawable.routing_toolbar_button);
setButtonTintList(ThemeUtils.isNightTheme(getContext()) ? R.color.routing_toolbar_icon_tint_night setButtonTintList(isNightTheme ? R.color.routing_toolbar_icon_tint_night : R.color.routing_toolbar_icon_tint);
: R.color.routing_toolbar_icon_tint);
} }
public void progress() public void progress()

View File

@@ -48,12 +48,6 @@
<!-- "Report a problem" predefined texts --> <!-- "Report a problem" predefined texts -->
<string name="problem_does_not_exist" translatable="false">The amenity has gone or never existed. This is an auto-generated note from CoMaps application: a user reports a POI that is visible on a map (which can be a month old), but cannot be found on the ground.</string> <string name="problem_does_not_exist" translatable="false">The amenity has gone or never existed. This is an auto-generated note from CoMaps application: a user reports a POI that is visible on a map (which can be a month old), but cannot be found on the ground.</string>
<!-- UI themes -->
<string name="theme_default" translatable="false">default</string>
<string name="theme_night" translatable="false">night</string>
<string name="theme_auto" translatable="false">auto</string>
<string name="theme_nav_auto" translatable="false">nav-auto</string>
<!-- Tags --> <!-- Tags -->
<string name="tag_menu_collapse" translatable="false">collapse</string> <string name="tag_menu_collapse" translatable="false">collapse</string>
<string name="tag_height_limited" translatable="false">height limited</string> <string name="tag_height_limited" translatable="false">height limited</string>

View File

@@ -53,14 +53,6 @@
<item>@string/nav_auto</item> <item>@string/nav_auto</item>
</string-array> </string-array>
<string-array name="map_style_values"
translatable="false">
<item>@string/theme_default</item>
<item>@string/theme_night</item>
<item>@string/theme_auto</item>
<item>@string/theme_nav_auto</item>
</string-array>
<string-array name="speed_cameras"> <string-array name="speed_cameras">
<item>@string/pref_tts_speedcams_auto</item> <item>@string/pref_tts_speedcams_auto</item>
<item>@string/pref_tts_speedcams_always</item> <item>@string/pref_tts_speedcams_always</item>

View File

@@ -130,7 +130,6 @@
android:title="@string/pref_map_style_title" android:title="@string/pref_map_style_title"
app:singleLineTitle="false" app:singleLineTitle="false"
android:entries="@array/map_style" android:entries="@array/map_style"
android:entryValues="@array/map_style_values"
android:order="1"/> android:order="1"/>
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:key="@string/pref_3d" android:key="@string/pref_3d"