android: Add theme picker
This commit is contained in:
		| @@ -107,6 +107,7 @@ class Settings { | ||||
|         const val SECTION_RENDERER = "Renderer" | ||||
|         const val SECTION_AUDIO = "Audio" | ||||
|         const val SECTION_CPU = "Cpu" | ||||
|         const val SECTION_THEME = "Theme" | ||||
|  | ||||
|         const val PREF_OVERLAY_INIT = "OverlayInit" | ||||
|         const val PREF_CONTROL_SCALE = "controlScale" | ||||
| @@ -134,6 +135,7 @@ class Settings { | ||||
|         const val PREF_MENU_SETTINGS_SHOW_OVERLAY = "EmulationMenuSettings_ShowOverlay" | ||||
|  | ||||
|         const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch" | ||||
|         const val PREF_THEME = "Theme" | ||||
|  | ||||
|         private val configFileSectionsMap: MutableMap<String, List<String>> = HashMap() | ||||
|  | ||||
|   | ||||
| @@ -3,11 +3,15 @@ | ||||
|  | ||||
| package org.yuzu.yuzu_emu.features.settings.ui | ||||
|  | ||||
| import android.content.SharedPreferences | ||||
| import android.os.Build | ||||
| import android.text.TextUtils | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| import androidx.preference.PreferenceManager | ||||
| import org.yuzu.yuzu_emu.R | ||||
| import org.yuzu.yuzu_emu.YuzuApplication | ||||
| import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.model.IntSetting | ||||
| import org.yuzu.yuzu_emu.features.settings.model.Settings | ||||
| import org.yuzu.yuzu_emu.features.settings.model.view.* | ||||
| @@ -21,12 +25,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | ||||
|     private val settingsActivity get() = fragmentView.activityView as AppCompatActivity | ||||
|     private val settings get() = fragmentView.activityView!!.settings | ||||
|  | ||||
|     private lateinit var preferences: SharedPreferences | ||||
|  | ||||
|     fun onCreate(menuTag: String, gameId: String) { | ||||
|         this.gameId = gameId | ||||
|         this.menuTag = menuTag | ||||
|     } | ||||
|  | ||||
|     fun onViewCreated() { | ||||
|         preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||||
|         loadSettingsList() | ||||
|     } | ||||
|  | ||||
| @@ -55,6 +62,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | ||||
|             Settings.SECTION_SYSTEM -> addSystemSettings(sl) | ||||
|             Settings.SECTION_RENDERER -> addGraphicsSettings(sl) | ||||
|             Settings.SECTION_AUDIO -> addAudioSettings(sl) | ||||
|             Settings.SECTION_THEME -> addThemeSettings(sl) | ||||
|             else -> { | ||||
|                 fragmentView.showToastMessage("Unimplemented menu", false) | ||||
|                 return | ||||
| @@ -99,6 +107,14 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | ||||
|                     Settings.SECTION_AUDIO | ||||
|                 ) | ||||
|             ) | ||||
|             add( | ||||
|                 SubmenuSetting( | ||||
|                     null, | ||||
|                     R.string.preferences_theme, | ||||
|                     0, | ||||
|                     Settings.SECTION_THEME | ||||
|                 ) | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -300,4 +316,45 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) | ||||
|             ) | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     private fun addThemeSettings(sl: ArrayList<SettingsItem>) { | ||||
|         settingsActivity.setTitle(R.string.preferences_theme) | ||||
|         sl.apply { | ||||
|             val theme: AbstractIntSetting = object : AbstractIntSetting { | ||||
|                 override var int: Int | ||||
|                     get() = preferences.getInt(Settings.PREF_THEME, 0) | ||||
|                     set(value) { | ||||
|                         preferences.edit().putInt(Settings.PREF_THEME, value).apply() | ||||
|                         settingsActivity.recreate() | ||||
|                     } | ||||
|                 override val key: String? = null | ||||
|                 override val section: String? = null | ||||
|                 override val isRuntimeEditable: Boolean = true | ||||
|                 override val valueAsString: String | ||||
|                     get() = preferences.getInt(Settings.PREF_THEME, 0).toString() | ||||
|             } | ||||
|  | ||||
|             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { | ||||
|                 add( | ||||
|                     SingleChoiceSetting( | ||||
|                         theme, | ||||
|                         R.string.change_app_theme, | ||||
|                         0, | ||||
|                         R.array.themeEntriesA12, | ||||
|                         R.array.themeValuesA12 | ||||
|                     ) | ||||
|                 ) | ||||
|             } else { | ||||
|                 add( | ||||
|                     SingleChoiceSetting( | ||||
|                         theme, | ||||
|                         R.string.change_app_theme, | ||||
|                         0, | ||||
|                         R.array.themeEntries, | ||||
|                         R.array.themeValues | ||||
|                     ) | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,12 +39,14 @@ import org.yuzu.yuzu_emu.model.HomeViewModel | ||||
| import org.yuzu.yuzu_emu.utils.* | ||||
| import java.io.IOException | ||||
|  | ||||
| class MainActivity : AppCompatActivity() { | ||||
| class MainActivity : AppCompatActivity(), ThemeProvider { | ||||
|     private lateinit var binding: ActivityMainBinding | ||||
|  | ||||
|     private val homeViewModel: HomeViewModel by viewModels() | ||||
|     private val gamesViewModel: GamesViewModel by viewModels() | ||||
|  | ||||
|     override var themeId: Int = 0 | ||||
|  | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         val splashScreen = installSplashScreen() | ||||
|         splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady } | ||||
| @@ -166,6 +168,11 @@ class MainActivity : AppCompatActivity() { | ||||
|         }.start() | ||||
|     } | ||||
|  | ||||
|     override fun onResume() { | ||||
|         ThemeHelper.setCorrectTheme(this) | ||||
|         super.onResume() | ||||
|     } | ||||
|  | ||||
|     override fun onDestroy() { | ||||
|         EmulationActivity.tryDismissRunningNotification(this) | ||||
|         super.onDestroy() | ||||
| @@ -180,6 +187,11 @@ class MainActivity : AppCompatActivity() { | ||||
|             windowInsets | ||||
|         } | ||||
|  | ||||
|     override fun setTheme(resId: Int) { | ||||
|         super.setTheme(resId) | ||||
|         themeId = resId | ||||
|     } | ||||
|  | ||||
|     private fun hasExtension(path: String, extension: String): Boolean { | ||||
|         return path.substring(path.lastIndexOf(".") + 1).contains(extension) | ||||
|     } | ||||
|   | ||||
| @@ -0,0 +1,11 @@ | ||||
| // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| package org.yuzu.yuzu_emu.ui.main | ||||
|  | ||||
| interface ThemeProvider { | ||||
|     /** | ||||
|      * Provides theme ID by overriding an activity's 'setTheme' method and returning that result | ||||
|      */ | ||||
|     var themeId: Int | ||||
| } | ||||
| @@ -10,15 +10,27 @@ import androidx.annotation.ColorInt | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| import androidx.core.content.ContextCompat | ||||
| import androidx.core.view.WindowCompat | ||||
| import com.google.android.material.color.MaterialColors | ||||
| import androidx.preference.PreferenceManager | ||||
| import org.yuzu.yuzu_emu.R | ||||
| import org.yuzu.yuzu_emu.YuzuApplication | ||||
| import org.yuzu.yuzu_emu.features.settings.model.Settings | ||||
| import org.yuzu.yuzu_emu.ui.main.ThemeProvider | ||||
| import kotlin.math.roundToInt | ||||
|  | ||||
| object ThemeHelper { | ||||
|     const val SYSTEM_BAR_ALPHA = 0.9f | ||||
|  | ||||
|     private const val DEFAULT = 0 | ||||
|     private const val MATERIAL_YOU = 1 | ||||
|  | ||||
|     @JvmStatic | ||||
|     fun setTheme(activity: AppCompatActivity) { | ||||
|         val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||||
|         when (preferences.getInt(Settings.PREF_THEME, 0)) { | ||||
|             DEFAULT -> activity.setTheme(R.style.Theme_Yuzu_Main) | ||||
|             MATERIAL_YOU -> activity.setTheme(R.style.Theme_Yuzu_Main_MaterialYou) | ||||
|         } | ||||
|  | ||||
|         val windowController = WindowCompat.getInsetsController( | ||||
|             activity.window, | ||||
|             activity.window.decorView | ||||
| @@ -60,4 +72,12 @@ object ThemeHelper { | ||||
|             Color.green(color), Color.blue(color) | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     fun setCorrectTheme(activity: AppCompatActivity) { | ||||
|         val currentTheme = (activity as ThemeProvider).themeId | ||||
|         setTheme(activity) | ||||
|         if (currentTheme != (activity as ThemeProvider).themeId) { | ||||
|             activity.recreate() | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -183,4 +183,20 @@ | ||||
|         <item>@string/gamepad_screenshot</item> | ||||
|     </string-array> | ||||
|  | ||||
|     <string-array name="themeEntries"> | ||||
|         <item>@string/theme_default</item> | ||||
|     </string-array> | ||||
|     <integer-array name="themeValues"> | ||||
|         <item>0</item> | ||||
|     </integer-array> | ||||
|  | ||||
|     <string-array name="themeEntriesA12"> | ||||
|         <item>@string/theme_default</item> | ||||
|         <item>@string/theme_material_you</item> | ||||
|     </string-array> | ||||
|     <integer-array name="themeValuesA12"> | ||||
|         <item>0</item> | ||||
|         <item>1</item> | ||||
|     </integer-array> | ||||
|  | ||||
| </resources> | ||||
|   | ||||
| @@ -103,6 +103,7 @@ | ||||
|     <string name="preferences_system">System</string> | ||||
|     <string name="preferences_graphics">Graphics</string> | ||||
|     <string name="preferences_audio">Audio</string> | ||||
|     <string name="preferences_theme">Theme and Color</string> | ||||
|  | ||||
|     <!-- ROM loading errors --> | ||||
|     <string name="loader_error_encrypted">Your ROM is encrypted</string> | ||||
| @@ -229,4 +230,9 @@ | ||||
|     <string name="preparing_shaders">Preparing shaders</string> | ||||
|     <string name="building_shaders">Building shaders</string> | ||||
|  | ||||
|     <!-- Theme options --> | ||||
|     <string name="change_app_theme">Change App Theme</string> | ||||
|     <string name="theme_default">Default</string> | ||||
|     <string name="theme_material_you">Material You</string> | ||||
|  | ||||
| </resources> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user