Merge pull request #11270 from t895/theme-mode
Android: Add theme mode switcher
This commit is contained in:
commit
f21edf6d5a
|
@ -96,7 +96,7 @@ android {
|
|||
dependencies {
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.5.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.5.1'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.3'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
|
|
|
@ -34,6 +34,8 @@ public enum IntSetting implements AbstractIntSetting
|
|||
MAIN_EMULATION_ORIENTATION(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
|
||||
"EmulationOrientation", ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE),
|
||||
MAIN_INTERFACE_THEME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "InterfaceTheme", 0),
|
||||
MAIN_INTERFACE_THEME_MODE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
|
||||
"InterfaceThemeMode", -1),
|
||||
MAIN_LAST_PLATFORM_TAB(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "LastPlatformTab", 0),
|
||||
MAIN_MOTION_CONTROLS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "MotionControls", 1),
|
||||
MAIN_IR_MODE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "IRMode",
|
||||
|
|
|
@ -8,6 +8,8 @@ import android.os.Build;
|
|||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.activities.UserDataActivity;
|
||||
|
@ -328,33 +330,37 @@ public final class SettingsFragmentPresenter
|
|||
|
||||
AbstractIntSetting appTheme = new AbstractIntSetting()
|
||||
{
|
||||
@Override public boolean isOverridden(Settings settings)
|
||||
@Override
|
||||
public boolean isOverridden(Settings settings)
|
||||
{
|
||||
return IntSetting.MAIN_INTERFACE_THEME.isOverridden(settings);
|
||||
}
|
||||
|
||||
@Override public boolean isRuntimeEditable()
|
||||
@Override
|
||||
public boolean isRuntimeEditable()
|
||||
{
|
||||
// This only affects app UI
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public boolean delete(Settings settings)
|
||||
@Override
|
||||
public boolean delete(Settings settings)
|
||||
{
|
||||
ThemeHelper.deleteThemeKey(mView.getActivity());
|
||||
ThemeHelper.deleteThemeKey((AppCompatActivity) mView.getActivity());
|
||||
return IntSetting.MAIN_INTERFACE_THEME.delete(settings);
|
||||
}
|
||||
|
||||
@Override public int getInt(Settings settings)
|
||||
@Override
|
||||
public int getInt(Settings settings)
|
||||
{
|
||||
return IntSetting.MAIN_INTERFACE_THEME.getInt(settings);
|
||||
}
|
||||
|
||||
@Override public void setInt(Settings settings, int newValue)
|
||||
@Override
|
||||
public void setInt(Settings settings, int newValue)
|
||||
{
|
||||
ThemeHelper.saveTheme(mView.getActivity(), newValue);
|
||||
IntSetting.MAIN_INTERFACE_THEME.setInt(settings, newValue);
|
||||
mView.getActivity().recreate();
|
||||
ThemeHelper.saveTheme((AppCompatActivity) mView.getActivity(), newValue);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -369,6 +375,45 @@ public final class SettingsFragmentPresenter
|
|||
sl.add(new SingleChoiceSetting(mContext, appTheme, R.string.change_theme, 0,
|
||||
R.array.themeEntries, R.array.themeValues));
|
||||
}
|
||||
|
||||
AbstractIntSetting themeMode = new AbstractIntSetting()
|
||||
{
|
||||
@Override
|
||||
public boolean isOverridden(Settings settings)
|
||||
{
|
||||
return IntSetting.MAIN_INTERFACE_THEME_MODE.isOverridden(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRuntimeEditable()
|
||||
{
|
||||
// This only affects app UI
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(Settings settings)
|
||||
{
|
||||
ThemeHelper.deleteThemeModeKey((AppCompatActivity) mView.getActivity());
|
||||
return IntSetting.MAIN_INTERFACE_THEME_MODE.delete(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(Settings settings)
|
||||
{
|
||||
return IntSetting.MAIN_INTERFACE_THEME_MODE.getInt(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInt(Settings settings, int newValue)
|
||||
{
|
||||
IntSetting.MAIN_INTERFACE_THEME_MODE.setInt(settings, newValue);
|
||||
ThemeHelper.saveThemeMode((AppCompatActivity) mView.getActivity(), newValue);
|
||||
}
|
||||
};
|
||||
|
||||
sl.add(new SingleChoiceSetting(mContext, themeMode, R.string.change_theme_mode, 0,
|
||||
R.array.themeModeEntries, R.array.themeModeValues));
|
||||
}
|
||||
|
||||
private void addAudioSettings(ArrayList<SettingsItem> sl)
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.widget.Toast;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
@ -87,6 +88,16 @@ public final class DirectoryInitialization
|
|||
.apply();
|
||||
}
|
||||
|
||||
if (IntSetting.MAIN_INTERFACE_THEME_MODE.getIntGlobal() !=
|
||||
preferences.getInt(ThemeHelper.CURRENT_THEME_MODE,
|
||||
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM))
|
||||
{
|
||||
preferences.edit()
|
||||
.putInt(ThemeHelper.CURRENT_THEME_MODE,
|
||||
IntSetting.MAIN_INTERFACE_THEME_MODE.getIntGlobal())
|
||||
.apply();
|
||||
}
|
||||
|
||||
if (wiimoteIniWritten)
|
||||
{
|
||||
// This has to be done after calling NativeLibrary.Initialize(),
|
||||
|
|
|
@ -10,7 +10,10 @@ import androidx.annotation.ColorInt;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.WindowCompat;
|
||||
import androidx.core.view.WindowInsetsControllerCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
|
@ -23,6 +26,7 @@ import org.dolphinemu.dolphinemu.ui.main.ThemeProvider;
|
|||
public class ThemeHelper
|
||||
{
|
||||
public static final String CURRENT_THEME = "current_theme";
|
||||
public static final String CURRENT_THEME_MODE = "current_theme_mode";
|
||||
|
||||
public static final int DEFAULT = 0;
|
||||
public static final int MONET = 1;
|
||||
|
@ -38,6 +42,7 @@ public class ThemeHelper
|
|||
// requested theme id is ready before the onCreate method of any given Activity.
|
||||
SharedPreferences preferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext());
|
||||
setThemeMode(activity);
|
||||
switch (preferences.getInt(CURRENT_THEME, DEFAULT))
|
||||
{
|
||||
case DEFAULT:
|
||||
|
@ -70,22 +75,88 @@ public class ThemeHelper
|
|||
}
|
||||
}
|
||||
|
||||
public static void saveTheme(@NonNull Activity activity, int themeValue)
|
||||
private static void setThemeMode(@NonNull AppCompatActivity activity)
|
||||
{
|
||||
SharedPreferences preferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext());
|
||||
preferences.edit().putInt(CURRENT_THEME, themeValue).apply();
|
||||
int themeMode = PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext())
|
||||
.getInt(CURRENT_THEME_MODE, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
|
||||
activity.getDelegate().setLocalNightMode(themeMode);
|
||||
|
||||
WindowInsetsControllerCompat windowController =
|
||||
WindowCompat.getInsetsController(activity.getWindow(),
|
||||
activity.getWindow().getDecorView());
|
||||
int systemReportedThemeMode =
|
||||
activity.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
|
||||
switch (themeMode)
|
||||
{
|
||||
case AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM:
|
||||
switch (systemReportedThemeMode)
|
||||
{
|
||||
case Configuration.UI_MODE_NIGHT_NO:
|
||||
setLightModeSystemBars(windowController);
|
||||
break;
|
||||
case Configuration.UI_MODE_NIGHT_YES:
|
||||
setDarkModeSystemBars(windowController);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AppCompatDelegate.MODE_NIGHT_NO:
|
||||
setLightModeSystemBars(windowController);
|
||||
break;
|
||||
case AppCompatDelegate.MODE_NIGHT_YES:
|
||||
setDarkModeSystemBars(windowController);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteThemeKey(@NonNull Activity activity)
|
||||
private static void setLightModeSystemBars(@NonNull WindowInsetsControllerCompat windowController)
|
||||
{
|
||||
SharedPreferences preferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext());
|
||||
preferences.edit().remove(CURRENT_THEME).apply();
|
||||
activity.setTheme(R.style.Theme_Dolphin_Main);
|
||||
windowController.setAppearanceLightStatusBars(true);
|
||||
windowController.setAppearanceLightNavigationBars(true);
|
||||
}
|
||||
|
||||
private static void setDarkModeSystemBars(@NonNull WindowInsetsControllerCompat windowController)
|
||||
{
|
||||
windowController.setAppearanceLightStatusBars(false);
|
||||
windowController.setAppearanceLightNavigationBars(false);
|
||||
}
|
||||
|
||||
public static void saveTheme(@NonNull AppCompatActivity activity, int themeValue)
|
||||
{
|
||||
PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext())
|
||||
.edit()
|
||||
.putInt(CURRENT_THEME, themeValue)
|
||||
.apply();
|
||||
activity.recreate();
|
||||
}
|
||||
|
||||
public static void deleteThemeKey(@NonNull AppCompatActivity activity)
|
||||
{
|
||||
PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext())
|
||||
.edit()
|
||||
.remove(CURRENT_THEME)
|
||||
.apply();
|
||||
activity.recreate();
|
||||
}
|
||||
|
||||
public static void saveThemeMode(@NonNull AppCompatActivity activity, int themeModeValue)
|
||||
{
|
||||
PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext())
|
||||
.edit()
|
||||
.putInt(CURRENT_THEME_MODE, themeModeValue)
|
||||
.apply();
|
||||
setThemeMode(activity);
|
||||
}
|
||||
|
||||
public static void deleteThemeModeKey(@NonNull AppCompatActivity activity)
|
||||
{
|
||||
PreferenceManager.getDefaultSharedPreferences(activity.getApplicationContext())
|
||||
.edit()
|
||||
.remove(CURRENT_THEME_MODE)
|
||||
.apply();
|
||||
setThemeMode(activity);
|
||||
}
|
||||
|
||||
public static void setCorrectTheme(AppCompatActivity activity)
|
||||
{
|
||||
int currentTheme = ((ThemeProvider) activity).getThemeId();
|
||||
|
@ -110,7 +181,7 @@ public class ThemeHelper
|
|||
}
|
||||
}
|
||||
|
||||
public static void setNavigationBarColor(Activity activity, @ColorInt int color)
|
||||
public static void setNavigationBarColor(@NonNull Activity activity, @ColorInt int color)
|
||||
{
|
||||
int gestureType = InsetsHelper.getSystemGestureType(activity.getApplicationContext());
|
||||
int orientation = activity.getResources().getConfiguration().orientation;
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorOnSurface"
|
||||
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
|
||||
</vector>
|
|
@ -2,7 +2,7 @@
|
|||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:state_selected="true"
|
||||
android:drawable="@color/dolphin_primary"/>
|
||||
android:drawable="@color/dolphin_blue"/>
|
||||
<item
|
||||
android:drawable="@color/tv_card_unselected"/>
|
||||
</selector>
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<bool name="lightSystemBars">false</bool>
|
||||
</resources>
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="Theme.V27.Dolphin" parent="Theme.Dolphin">
|
||||
<item name="android:windowLightNavigationBar">@bool/lightSystemBars</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Dolphin.Main" parent="Theme.V27.Dolphin" />
|
||||
</resources>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="Theme.V29.Dolphin" parent="Theme.V27.Dolphin">
|
||||
<style name="Theme.V29.Dolphin" parent="Theme.Dolphin">
|
||||
<item name="android:enforceStatusBarContrast">false</item>
|
||||
<item name="android:enforceNavigationBarContrast">false</item>
|
||||
</style>
|
||||
|
|
|
@ -507,6 +507,17 @@
|
|||
<item>4</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="themeModeEntries">
|
||||
<item>Follow System</item>
|
||||
<item>Light</item>
|
||||
<item>Dark</item>
|
||||
</string-array>
|
||||
<integer-array name="themeModeValues">
|
||||
<item>-1</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="synchronizeGpuThreadEntries">
|
||||
<item>Never</item>
|
||||
<item>On Idle Skipping</item>
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<bool name="lightSystemBars">true</bool>
|
||||
</resources>
|
|
@ -196,6 +196,7 @@
|
|||
<string name="show_titles_in_game_list">Show Titles in Game List</string>
|
||||
<string name="show_titles_in_game_list_description">Show the title and creator below each game cover.</string>
|
||||
<string name="change_theme">Change App Theme</string>
|
||||
<string name="change_theme_mode">Change Theme Mode</string>
|
||||
|
||||
<!-- Online Update Region Select Fragment -->
|
||||
<string name="region_select_title">Please select a region</string>
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
<style name="DolphinTVDialog" parent="Theme.Material3.DayNight.Dialog.Alert">
|
||||
<item name="colorSurface">@color/dolphin_inverseOnSurface</item>
|
||||
<item name="colorPrimary">@color/dolphin_primary</item>
|
||||
<item name="colorPrimary">@color/dolphin_blue</item>
|
||||
</style>
|
||||
|
||||
<style name="DolphinButton" parent="Widget.Material3.Button.TextButton.Dialog">
|
||||
|
|
|
@ -47,9 +47,6 @@
|
|||
<item name="android:windowAllowEnterTransitionOverlap">true</item>
|
||||
<item name="android:windowAllowReturnTransitionOverlap">true</item>
|
||||
|
||||
<item name="homeAsUpIndicator">@drawable/ic_back</item>
|
||||
|
||||
<item name="android:windowLightStatusBar" tools:targetApi="m">@bool/lightSystemBars</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">default</item>
|
||||
|
||||
<item name="materialAlertDialogTheme">@style/DolphinMaterialDialog</item>
|
||||
|
@ -58,7 +55,7 @@
|
|||
<item name="materialDividerStyle">@style/DolphinDivider</item>
|
||||
</style>
|
||||
|
||||
<!-- Trick for API >= 27 specific changes -->
|
||||
<!-- Trick for API >= 29 specific changes -->
|
||||
<style name="Theme.Dolphin.Main" parent="Theme.Dolphin" />
|
||||
|
||||
<style name="Theme.Dolphin.Main.Material" parent="Theme.Dolphin.Main">
|
||||
|
|
|
@ -39,10 +39,12 @@ bool IsSettingSaveable(const Config::Location& config_location)
|
|||
// TODO: Kill the current Android controller mappings system
|
||||
if (config_location.section == "Android")
|
||||
{
|
||||
static constexpr std::array<const char*, 12> android_setting_saveable = {
|
||||
"ControlScale", "ControlOpacity", "EmulationOrientation", "JoystickRelCenter",
|
||||
"LastPlatformTab", "MotionControls", "PhoneRumble", "ShowInputOverlay",
|
||||
"IRMode", "IRAlwaysRecenter", "ShowGameTitles", "InterfaceTheme"};
|
||||
static constexpr std::array<const char*, 13> android_setting_saveable = {
|
||||
"ControlScale", "ControlOpacity", "EmulationOrientation",
|
||||
"JoystickRelCenter", "LastPlatformTab", "MotionControls",
|
||||
"PhoneRumble", "ShowInputOverlay", "IRMode",
|
||||
"IRAlwaysRecenter", "ShowGameTitles", "InterfaceTheme",
|
||||
"InterfaceThemeMode"};
|
||||
|
||||
return std::any_of(
|
||||
android_setting_saveable.cbegin(), android_setting_saveable.cend(),
|
||||
|
|
Loading…
Reference in New Issue