[android] Implement Light, Dark, and System modes on android(Auto)

closes #749

Changed from the existing night modes (on, off, auto), to "appearence"
modes:
	- Light;
	- Dark;
	- System;

System mode follows whatever mode the user's device is in. This
implementation works for both normal android and AndroidAuto.

Main changes:
	- added necessary strings to XML files;
	- changed the position and option names of the "map style
	  preferences";
	- implemented system mode, and some helper methods on
	  ThemeSwitcher.java and ThemeUtils.java;
	- added uiMode changes detection to all activities;
	- removed "auto" mode implementation;

Signed-off-by: Sebastiao Sousa <sebastiao.sousa@tecnico.ulisboa.pt>
Co-authored-by: Francisco Nael Salgado <francisco.nael.salgado@tecnico.ulisboa.pt>
This commit is contained in:
Sebastiao Sousa 2024-07-08 23:16:25 +01:00
parent a58ee13168
commit 20a5f1e510
14 changed files with 132 additions and 122 deletions

View file

@ -331,10 +331,13 @@
</intent-filter>
</activity>
<activity
android:name="app.organicmaps.base.BaseMwmFragmentActivity"
android:configChanges="uiMode" />
<activity
android:name="app.organicmaps.DownloadResourcesLegacyActivity"
android:configChanges="orientation|screenLayout|screenSize"/>
android:configChanges="uiMode|orientation|screenLayout|screenSize" />
<activity-alias
android:name="app.organicmaps.DownloadResourcesActivity"
@ -355,21 +358,21 @@
<activity
android:name="app.organicmaps.downloader.DownloaderActivity"
android:configChanges="orientation|screenLayout|screenSize"
android:configChanges="uiMode|orientation|screenLayout|screenSize"
android:label="@string/download_maps"
android:parentActivityName="app.organicmaps.MwmActivity"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="app.organicmaps.search.SearchActivity"
android:configChanges="orientation|screenLayout|screenSize"
android:configChanges="uiMode|orientation|screenLayout|screenSize"
android:label="@string/search_map"
android:parentActivityName="app.organicmaps.MwmActivity"
android:windowSoftInputMode="stateVisible|adjustResize" />
<activity
android:name="app.organicmaps.settings.SettingsActivity"
android:configChanges="orientation|screenLayout|screenSize"
android:configChanges="uiMode|orientation|screenLayout|screenSize"
android:label="@string/settings"
android:parentActivityName="app.organicmaps.MwmActivity" />
@ -377,6 +380,7 @@
android:name="app.organicmaps.help.HelpActivity"
android:label="@string/about_menu_title"
android:parentActivityName="app.organicmaps.MwmActivity"
android:configChanges="uiMode"
android:exported="false">
<intent-filter>
<action android:name="app.organicmaps.help.HelpActivity" />
@ -386,54 +390,62 @@
<activity
android:name="app.organicmaps.bookmarks.BookmarkCategoriesActivity"
android:configChanges="orientation|screenLayout|screenSize"
android:configChanges="uiMode|orientation|screenLayout|screenSize"
android:label="@string/bookmarks_and_tracks"
android:parentActivityName="app.organicmaps.MwmActivity"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="app.organicmaps.bookmarks.BookmarkListActivity"
android:configChanges="orientation|screenLayout|screenSize"
android:configChanges="uiMode|orientation|screenLayout|screenSize"
android:label="@string/bookmarks"
android:parentActivityName="app.organicmaps.bookmarks.BookmarkCategoriesActivity"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="app.organicmaps.editor.EditorActivity"
android:configChanges="orientation|screenLayout|screenSize"
android:configChanges="uiMode|orientation|screenLayout|screenSize"
android:label="@string/edit_place"
android:parentActivityName="app.organicmaps.MwmActivity"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="app.organicmaps.editor.ProfileActivity"
android:configChanges="uiMode"
android:parentActivityName="app.organicmaps.settings.SettingsActivity" />
<activity
android:name="app.organicmaps.editor.FeatureCategoryActivity"
android:parentActivityName="app.organicmaps.MwmActivity"
android:configChanges="uiMode"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="app.organicmaps.editor.ReportActivity"
android:configChanges="uiMode"
android:parentActivityName="app.organicmaps.MwmActivity" />
<activity
android:name="app.organicmaps.editor.OsmLoginActivity"
android:configChanges="uiMode"
android:parentActivityName="app.organicmaps.MwmActivity" />
<activity
android:name="app.organicmaps.bookmarks.BookmarkCategorySettingsActivity"
android:label="@string/edit"
android:configChanges="uiMode"
android:windowSoftInputMode="stateVisible"/>
<activity
android:name="app.organicmaps.widget.placepage.PlaceDescriptionActivity"
android:configChanges="uiMode"
android:label="@string/place_description_title"/>
<activity
android:name="app.organicmaps.settings.DrivingOptionsActivity"
android:configChanges="uiMode"
android:label="@string/driving_options_title"/>
<activity
android:name="app.organicmaps.MapPlaceholderActivity"/>
android:name="app.organicmaps.MapPlaceholderActivity"
android:configChanges="uiMode" />
<service
android:name="app.organicmaps.car.CarAppService"
android:foregroundServiceType="location"

View file

@ -1,11 +1,9 @@
package app.organicmaps;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import androidx.activity.result.ActivityResultLauncher;
@ -15,11 +13,11 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatActivity;
import app.organicmaps.display.DisplayManager;
import app.organicmaps.location.LocationHelper;
import app.organicmaps.util.Config;
import app.organicmaps.util.LocationUtils;
import app.organicmaps.util.ThemeSwitcher;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.concurrency.UiThread;
import app.organicmaps.util.log.Logger;
@ -28,6 +26,9 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.io.IOException;
import java.util.Objects;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
public class SplashActivity extends AppCompatActivity
{
private static final String TAG = SplashActivity.class.getSimpleName();
@ -103,6 +104,13 @@ public class SplashActivity extends AppCompatActivity
mPermissionRequest = null;
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
ThemeSwitcher.INSTANCE.restart(false);
UiThread.runLater(this::recreate);
}
private void showFatalErrorDialog(@StringRes int titleId, @StringRes int messageId)
{
mCanceled = true;

View file

@ -3,6 +3,7 @@ package app.organicmaps.base;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.media.AudioManager;
import android.os.Bundle;
import android.view.MenuItem;
@ -16,12 +17,12 @@ import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentFactory;
import androidx.fragment.app.FragmentManager;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.SplashActivity;
import app.organicmaps.util.Config;
import app.organicmaps.util.RtlUtils;
import app.organicmaps.util.ThemeSwitcher;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.concurrency.UiThread;
import app.organicmaps.util.log.Logger;
@ -128,6 +129,14 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
}
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
ThemeSwitcher.INSTANCE.restart(false);
UiThread.runLater(this::recreate);
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{

View file

@ -11,7 +11,6 @@ import androidx.car.app.model.Row;
import androidx.car.app.model.Template;
import androidx.car.app.navigation.model.MapWithContentTemplate;
import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.R;
import app.organicmaps.car.SurfaceRenderer;
import app.organicmaps.car.screens.base.BaseMapScreen;
@ -56,7 +55,7 @@ public class ThemeScreen extends BaseMapScreen
{
final ItemList.Builder builder = new ItemList.Builder();
final ThemeUtils.ThemeMode currentThemeMode = ThemeUtils.getThemeMode(getCarContext());
builder.addItem(createRadioButton(ThemeUtils.ThemeMode.AUTO, currentThemeMode));
builder.addItem(createRadioButton(ThemeUtils.ThemeMode.FOLLOW_SYSTEM, currentThemeMode));
builder.addItem(createRadioButton(ThemeUtils.ThemeMode.NIGHT, currentThemeMode));
builder.addItem(createRadioButton(ThemeUtils.ThemeMode.LIGHT, currentThemeMode));
return new ListTemplate.Builder().setHeader(createHeader()).setSingleList(builder.build()).build();

View file

@ -8,7 +8,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.annotation.UiThread;
import androidx.car.app.CarContext;
import app.organicmaps.Framework;
import app.organicmaps.R;
import app.organicmaps.routing.RoutingController;
@ -17,9 +16,9 @@ public final class ThemeUtils
{
public enum ThemeMode
{
AUTO(R.string.auto, R.string.theme_auto),
LIGHT(R.string.off, R.string.theme_default),
NIGHT(R.string.on, R.string.theme_night);
LIGHT(R.string.light, R.string.theme_default),
NIGHT(R.string.dark, R.string.theme_night),
FOLLOW_SYSTEM(R.string.system, R.string.theme_follow_system);
ThemeMode(@StringRes int titleId, @StringRes int prefsKeyId)
{
@ -58,7 +57,7 @@ public final class ThemeUtils
@UiThread
public static void update(@NonNull CarContext context, @NonNull ThemeMode oldThemeMode)
{
final ThemeMode newThemeMode = oldThemeMode == ThemeMode.AUTO ? (context.isDarkMode() ? ThemeMode.NIGHT : ThemeMode.LIGHT) : oldThemeMode;
final ThemeMode newThemeMode = oldThemeMode == ThemeMode.FOLLOW_SYSTEM ? (context.isDarkMode() ? ThemeMode.NIGHT : ThemeMode.LIGHT) : oldThemeMode;
@Framework.MapStyle
int newMapStyle;
@ -74,7 +73,7 @@ public final class ThemeUtils
public static boolean isNightMode(@NonNull CarContext context)
{
final ThemeMode themeMode = getThemeMode(context);
return themeMode == ThemeMode.NIGHT || (themeMode == ThemeMode.AUTO && context.isDarkMode());
return themeMode == ThemeMode.NIGHT || (themeMode == ThemeMode.FOLLOW_SYSTEM && context.isDarkMode());
}
@SuppressLint("ApplySharedPref")
@ -88,13 +87,13 @@ public final class ThemeUtils
@NonNull
public static ThemeMode getThemeMode(@NonNull CarContext context)
{
final String autoTheme = context.getString(R.string.theme_auto);
final String followSystemTheme = context.getString(R.string.theme_follow_system);
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);
final String themeMode = getSharedPreferences(context).getString(THEME_KEY, followSystemTheme);
if (themeMode.equals(autoTheme))
return ThemeMode.AUTO;
if (themeMode.equals(followSystemTheme))
return ThemeMode.FOLLOW_SYSTEM;
else if (themeMode.equals(lightTheme))
return ThemeMode.LIGHT;
else if (themeMode.equals(nightTheme))

View file

@ -1,7 +1,6 @@
package app.organicmaps.help;
import androidx.fragment.app.Fragment;
import app.organicmaps.base.BaseToolbarActivity;
public class HelpActivity extends BaseToolbarActivity

View file

@ -22,6 +22,7 @@ import app.organicmaps.help.HelpActivity;
import app.organicmaps.location.LocationHelper;
import app.organicmaps.location.LocationProviderFactory;
import app.organicmaps.routing.RoutingOptions;
import app.organicmaps.search.SearchRecents;
import app.organicmaps.util.Config;
import app.organicmaps.util.NetworkPolicy;
import app.organicmaps.util.PowerManagment;
@ -29,7 +30,6 @@ import app.organicmaps.util.SharedPropertiesUtils;
import app.organicmaps.util.ThemeSwitcher;
import app.organicmaps.util.Utils;
import app.organicmaps.util.log.LogsManager;
import app.organicmaps.search.SearchRecents;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
public class SettingsPrefsFragment extends BaseXmlSettingsFragment
@ -455,7 +455,7 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment
{
DEFAULT(R.string.theme_default),
NIGHT(R.string.theme_night),
AUTO(R.string.theme_auto);
FOLLOW_SYSTEM(R.string.theme_follow_system);
private final int mModeStringId;
@ -472,7 +472,7 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment
if (context.getResources().getString(each.mModeStringId).equals(src))
return each;
}
return AUTO;
return FOLLOW_SYSTEM;
}
}

View file

@ -6,7 +6,6 @@ import android.os.Build;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceManager;
import app.organicmaps.BuildConfig;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
@ -255,12 +254,12 @@ public final class Config
@NonNull
public static String getUiThemeSettings(@NonNull Context context)
{
String autoTheme = MwmApplication.from(context).getString(R.string.theme_auto);
String res = getString(KEY_MISC_UI_THEME_SETTINGS, autoTheme);
if (ThemeUtils.isValidTheme(context, res) || ThemeUtils.isAutoTheme(context, res))
String followSystemTheme = MwmApplication.from(context).getString(R.string.theme_follow_system);
String res = getString(KEY_MISC_UI_THEME_SETTINGS, followSystemTheme);
if (ThemeUtils.isValidTheme(context, res) || ThemeUtils.isFollowSystemTheme(context, res))
return res;
return autoTheme;
return followSystemTheme;
}
public static boolean setUiThemeSettings(@NonNull Context context, String theme)

View file

@ -1,21 +1,15 @@
package app.organicmaps.util;
import android.app.Activity;
import android.app.UiModeManager;
import android.content.Context;
import android.location.Location;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatDelegate;
import app.organicmaps.Framework;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.display.DisplayManager;
import app.organicmaps.downloader.DownloaderStatusIcon;
import app.organicmaps.location.LocationHelper;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.util.concurrency.UiThread;
public enum ThemeSwitcher
{
@ -24,38 +18,6 @@ public enum ThemeSwitcher
private static final long CHECK_INTERVAL_MS = 30 * 60 * 1000;
private static boolean mRendererActive = false;
private final Runnable mAutoThemeChecker = new Runnable()
{
@Override
public void run()
{
String nightTheme = MwmApplication.from(mContext).getString(R.string.theme_night);
String defaultTheme = MwmApplication.from(mContext).getString(R.string.theme_default);
String theme = defaultTheme;
if (RoutingController.get().isNavigating())
{
Location last = LocationHelper.from(mContext).getSavedLocation();
if (last == null)
{
theme = Config.getCurrentUiTheme(mContext);
}
else
{
boolean day = Framework.nativeIsDayTime(System.currentTimeMillis() / 1000,
last.getLatitude(), last.getLongitude());
theme = (day ? defaultTheme : nightTheme);
}
}
setThemeAndMapStyle(theme);
UiThread.cancelDelayedTasks(mAutoThemeChecker);
if (ThemeUtils.isAutoTheme(mContext))
UiThread.runLater(mAutoThemeChecker, CHECK_INTERVAL_MS);
}
};
@SuppressWarnings("NotNullFieldNotInitialized")
@NonNull
private Context mContext;
@ -78,33 +40,30 @@ public enum ThemeSwitcher
public void restart(boolean isRendererActive)
{
mRendererActive = isRendererActive;
String theme = Config.getUiThemeSettings(mContext);
if (ThemeUtils.isAutoTheme(mContext, theme))
{
mAutoThemeChecker.run();
return;
}
final String theme = Config.getUiThemeSettings(mContext);
setAndroidTheme(theme);
UiThread.cancelDelayedTasks(mAutoThemeChecker);
setThemeAndMapStyle(theme);
final String themeToApply = ThemeUtils.getAndroidTheme(mContext);
final int style = getStyle(themeToApply);
setThemeAndMapStyle(themeToApply, style);
}
private void setThemeAndMapStyle(@NonNull String theme)
private void setAndroidTheme(@NonNull String theme)
{
UiModeManager uiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
String oldTheme = Config.getCurrentUiTheme(mContext);
@Framework.MapStyle
int oldStyle = Framework.nativeGetMapStyle();
if (ThemeUtils.isFollowSystemTheme(mContext, theme))
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
else if (ThemeUtils.isNightTheme(mContext, theme))
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
else if (ThemeUtils.isDefaultTheme(mContext, theme))
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
private int getStyle(@NonNull String theme)
{
@Framework.MapStyle
int style;
if (ThemeUtils.isNightTheme(mContext, theme))
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_YES);
else
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
if (RoutingController.get().isVehicleNavigation())
style = Framework.MAP_STYLE_VEHICLE_DARK;
else if (Framework.nativeIsOutdoorsLayerEnabled())
@ -114,11 +73,6 @@ public enum ThemeSwitcher
}
else
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_NO);
else
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
if (RoutingController.get().isVehicleNavigation())
style = Framework.MAP_STYLE_VEHICLE_CLEAR;
else if (Framework.nativeIsOutdoorsLayerEnabled())
@ -127,6 +81,13 @@ public enum ThemeSwitcher
style = Framework.MAP_STYLE_CLEAR;
}
return style;
}
private void setThemeAndMapStyle(@NonNull String theme, @Framework.MapStyle int style)
{
String oldTheme = Config.getCurrentUiTheme(mContext);
if (!theme.equals(oldTheme))
{
Config.setCurrentUiTheme(mContext, theme);

View file

@ -1,6 +1,7 @@
package app.organicmaps.util;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.util.TypedValue;
@ -8,7 +9,7 @@ import androidx.annotation.AttrRes;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.StyleRes;
import androidx.appcompat.app.AppCompatDelegate;
import app.organicmaps.R;
public final class ThemeUtils
@ -45,6 +46,25 @@ public final class ThemeUtils
return VALUE_BUFFER.resourceId;
}
public static String getAndroidTheme(@NonNull Context context)
{
String nightTheme = context.getString(R.string.theme_night);
String defaultTheme = context.getString(R.string.theme_default);
if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES)
return nightTheme;
if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_NO)
return defaultTheme;
int nightModeFlags = context.getResources()
.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
if (nightModeFlags == Configuration.UI_MODE_NIGHT_YES)
return nightTheme;
else
return defaultTheme;
}
public static boolean isDefaultTheme(@NonNull Context context)
{
return isDefaultTheme(context, Config.getCurrentUiTheme(context));
@ -67,15 +87,15 @@ public final class ThemeUtils
return nightTheme.equals(theme);
}
public static boolean isAutoTheme(@NonNull Context context)
public static boolean isFollowSystemTheme(@NonNull Context context)
{
return isAutoTheme(context, Config.getCurrentUiTheme(context));
return isFollowSystemTheme(context, Config.getCurrentUiTheme(context));
}
public static boolean isAutoTheme(@NonNull Context context, String theme)
public static boolean isFollowSystemTheme(@NonNull Context context, String theme)
{
String autoTheme = context.getString(R.string.theme_auto);
return autoTheme.equals(theme);
String followSystemTheme = context.getString(R.string.theme_follow_system);
return followSystemTheme.equals(theme);
}
public static boolean isValidTheme(@NonNull Context context, String theme)

View file

@ -50,7 +50,7 @@
<!-- 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_follow_system" translatable="false">follow system</string>
<!-- Tags -->
<string name="tag_menu_collapse" translatable="false">collapse</string>

View file

@ -23,18 +23,16 @@
<item>0</item>
<item>1</item>
</string-array>
<string-array name="map_style">
<item>@string/off</item>
<item>@string/on</item>
<item>@string/auto</item>
<string-array name="appearance">
<item>@string/light</item>
<item>@string/dark</item>
<item>@string/system</item>
</string-array>
<string-array name="map_style_values"
<string-array name="appearance_values"
translatable="false">
<item>@string/theme_default</item>
<item>@string/theme_night</item>
<item>@string/theme_auto</item>
<item>@string/theme_follow_system</item>
</string-array>
<string-array name="speed_cameras">

View file

@ -221,13 +221,19 @@
<string name="pref_zoom_title">Zoom buttons</string>
<string name="pref_zoom_summary">Display on the map</string>
<!-- Settings «Map» category: «Night style» title -->
<string name="pref_map_style_title">Night Mode</string>
<string name="pref_map_style_title">Appearance</string>
<!-- Generic «Off» string -->
<string name="off">Off</string>
<!-- Generic «On» string -->
<string name="on">On</string>
<!-- Generic «Auto» string -->
<string name="auto">Auto</string>
<!-- Generic «Light» string -->
<string name="light">Light</string>
<!-- Generic «Dark» string -->
<string name="dark">Dark</string>
<!-- Generic «System» string -->
<string name="system">System</string>
<!-- Settings «Map» category: «Perspective view» title -->
<string name="pref_map_3d_title">Perspective view</string>
<!-- Settings «Map» category: «3D buildings» title -->

View file

@ -97,39 +97,39 @@
android:summary="@string/enable_show_on_lock_screen_description"
android:defaultValue="true"
android:order="17"/>
<ListPreference
android:entries="@array/appearance"
android:entryValues="@array/appearance_values"
android:key="@string/pref_map_style"
android:order="18"
android:title="@string/pref_map_style_title"
app:singleLineTitle="false" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:key="@string/pref_navigation"
android:title="@string/prefs_group_route"
android:order="3">
<ListPreference
android:key="@string/pref_map_style"
android:title="@string/pref_map_style_title"
app:singleLineTitle="false"
android:entries="@array/map_style"
android:entryValues="@array/map_style_values"
android:order="1"/>
<SwitchPreferenceCompat
android:key="@string/pref_3d"
android:title="@string/pref_map_3d_title"
app:singleLineTitle="false"
android:order="2"/>
android:order="1" />
<SwitchPreferenceCompat
android:key="@string/pref_auto_zoom"
android:title="@string/pref_map_auto_zoom"
app:singleLineTitle="false"
android:order="3"/>
android:order="2" />
<Preference
android:key="@string/pref_tts_screen"
android:title="@string/pref_tts_enable_title"
app:singleLineTitle="false"
android:persistent="false"
android:order="4">
android:order="3">
</Preference>
<PreferenceScreen
android:key="@string/prefs_routing"
android:order="5"
android:order="4"
android:title="@string/driving_options_title">
<intent
android:targetClass="app.organicmaps.settings.DrivingOptionsActivity"