Browse Source

[android] Add quick settings menu to emulation fragment (#3342)

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3342
Reviewed-by: DraVee <dravee@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: Nekle <224100951+ne-kle@users.noreply.github.com>
Co-committed-by: Nekle <224100951+ne-kle@users.noreply.github.com>
lizzie/audio-remove-recursive-lock
Nekle 3 weeks ago
committed by crueter
parent
commit
29fad5a89e
No known key found for this signature in database GPG Key ID: 425ACD2D4830EBC6
  1. 208
      src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/QuickSettings.kt
  2. 141
      src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
  3. 23
      src/android/app/src/main/res/layout/fragment_emulation.xml
  4. 5
      src/android/app/src/main/res/layout/item_quick_settings_divider.xml
  5. 140
      src/android/app/src/main/res/layout/item_quick_settings_menu.xml
  6. 37
      src/android/app/src/main/res/layout/item_quick_settings_status.xml
  7. 34
      src/android/app/src/main/res/layout/layout_quick_settings.xml
  8. 5
      src/android/app/src/main/res/menu/menu_in_game.xml
  9. 2
      src/android/app/src/main/res/values/strings.xml

208
src/android/app/src/main/java/org/yuzu/yuzu_emu/dialogs/QuickSettings.kt

@ -0,0 +1,208 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
package org.yuzu.yuzu_emu.dialogs
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.RadioGroup
import android.widget.TextView
import androidx.drawerlayout.widget.DrawerLayout
import com.google.android.material.color.MaterialColors
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.fragments.EmulationFragment
import org.yuzu.yuzu_emu.utils.NativeConfig
import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
import org.yuzu.yuzu_emu.features.settings.model.AbstractShortSetting
import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting
class QuickSettings(val emulationFragment: EmulationFragment) {
// Kinda a crappy workaround to get a title from setting keys
// Idk how to do this witthout hardcoding every single one
private fun getSettingTitle(settingKey: String): String {
return settingKey.replace("_", " ").split(" ")
.joinToString(" ") { it.replaceFirstChar { c -> c.uppercase() } }
}
private fun saveSettings() {
if (emulationFragment.shouldUseCustom) {
NativeConfig.savePerGameConfig()
} else {
NativeConfig.saveGlobalConfig()
}
}
fun addPerGameConfigStatusIndicator(container: ViewGroup) {
val inflater = LayoutInflater.from(emulationFragment.requireContext())
val statusView = inflater.inflate(R.layout.item_quick_settings_status, container, false)
val statusIcon = statusView.findViewById<android.widget.ImageView>(R.id.status_icon)
val statusText = statusView.findViewById<TextView>(R.id.status_text)
statusIcon.setImageResource(R.drawable.ic_settings_outline)
statusText.text = emulationFragment.getString(R.string.using_per_game_config)
statusText.setTextColor(
MaterialColors.getColor(
statusText,
com.google.android.material.R.attr.colorPrimary
)
)
container.addView(statusView)
}
// settings
fun addIntSetting(
container: ViewGroup,
setting: IntSetting,
namesArrayId: Int,
valuesArrayId: Int
) {
val inflater = LayoutInflater.from(emulationFragment.requireContext())
val itemView = inflater.inflate(R.layout.item_quick_settings_menu, container, false)
val headerView = itemView.findViewById<ViewGroup>(R.id.setting_header)
val titleView = itemView.findViewById<TextView>(R.id.setting_title)
val valueView = itemView.findViewById<TextView>(R.id.setting_value)
val expandIcon = itemView.findViewById<android.widget.ImageView>(R.id.expand_icon)
val radioGroup = itemView.findViewById<RadioGroup>(R.id.radio_group)
titleView.text = getSettingTitle(setting.key)
val names = emulationFragment.resources.getStringArray(namesArrayId)
val values = emulationFragment.resources.getIntArray(valuesArrayId)
val currentIndex = values.indexOf(setting.getInt())
valueView.text = if (currentIndex >= 0) names[currentIndex] else "Null"
headerView.visibility = View.VISIBLE
var isExpanded = false
names.forEachIndexed { index, name ->
val radioButton = com.google.android.material.radiobutton.MaterialRadioButton(emulationFragment.requireContext())
radioButton.text = name
radioButton.id = View.generateViewId()
radioButton.isChecked = index == currentIndex
radioButton.setPadding(16, 8, 16, 8)
radioButton.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
setting.setInt(values[index])
saveSettings()
valueView.text = name
}
}
radioGroup.addView(radioButton)
}
headerView.setOnClickListener {
isExpanded = !isExpanded
if (isExpanded) {
radioGroup.visibility = View.VISIBLE
expandIcon.animate().rotation(180f).setDuration(200).start()
} else {
radioGroup.visibility = View.GONE
expandIcon.animate().rotation(0f).setDuration(200).start()
}
}
container.addView(itemView)
}
fun addBooleanSetting(
container: ViewGroup,
setting: BooleanSetting
) {
val inflater = LayoutInflater.from(emulationFragment.requireContext())
val itemView = inflater.inflate(R.layout.item_quick_settings_menu, container, false)
val switchContainer = itemView.findViewById<ViewGroup>(R.id.switch_container)
val titleView = itemView.findViewById<TextView>(R.id.switch_title)
val switchView = itemView.findViewById<com.google.android.material.materialswitch.MaterialSwitch>(R.id.setting_switch)
titleView.text = getSettingTitle(setting.key)
switchContainer.visibility = View.VISIBLE
switchView.isChecked = setting.getBoolean()
switchView.setOnCheckedChangeListener { _, isChecked ->
setting.setBoolean(isChecked)
saveSettings()
}
switchContainer.setOnClickListener {
switchView.toggle()
}
container.addView(itemView)
}
fun addSliderSetting(
container: ViewGroup,
setting: AbstractSetting,
minValue: Int = 0,
maxValue: Int = 100,
units: String = ""
) {
val inflater = LayoutInflater.from(emulationFragment.requireContext())
val itemView = inflater.inflate(R.layout.item_quick_settings_menu, container, false)
val sliderContainer = itemView.findViewById<ViewGroup>(R.id.slider_container)
val titleView = itemView.findViewById<TextView>(R.id.slider_title)
val valueDisplay = itemView.findViewById<TextView>(R.id.slider_value_display)
val slider = itemView.findViewById<com.google.android.material.slider.Slider>(R.id.setting_slider)
titleView.text = getSettingTitle(setting.key)
sliderContainer.visibility = View.VISIBLE
slider.valueFrom = minValue.toFloat()
slider.valueTo = maxValue.toFloat()
slider.stepSize = 1f
val currentValue = when (setting) {
is AbstractShortSetting -> setting.getShort(needsGlobal = false).toInt()
is AbstractIntSetting -> setting.getInt(needsGlobal = false)
else -> 0
}
slider.value = currentValue.toFloat().coerceIn(minValue.toFloat(), maxValue.toFloat())
val displayValue = "${slider.value.toInt()}$units"
valueDisplay.text = displayValue
slider.addOnChangeListener { _, value, chanhed ->
if (chanhed) {
val intValue = value.toInt()
when (setting) {
is AbstractShortSetting -> setting.setShort(intValue.toShort())
is AbstractIntSetting -> setting.setInt(intValue)
}
saveSettings()
valueDisplay.text = "$intValue$units"
}
}
slider.setOnTouchListener { _, event ->
val drawer = emulationFragment.view?.findViewById<DrawerLayout>(R.id.drawer_layout)
when (event.action) {
MotionEvent.ACTION_DOWN -> {
drawer?.requestDisallowInterceptTouchEvent(true)
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
drawer?.requestDisallowInterceptTouchEvent(false)
}
}
false
}
container.addView(itemView)
}
fun addDivider(container: ViewGroup) {
val inflater = LayoutInflater.from(emulationFragment.requireContext())
val dividerView = inflater.inflate(R.layout.item_quick_settings_divider, container, false)
container.addView(dividerView)
}
}

141
src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
@ -68,12 +68,14 @@ import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.activities.EmulationActivity
import org.yuzu.yuzu_emu.databinding.DialogOverlayAdjustBinding
import org.yuzu.yuzu_emu.databinding.FragmentEmulationBinding
import org.yuzu.yuzu_emu.dialogs.QuickSettings
import org.yuzu.yuzu_emu.features.input.NativeInput
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.Settings.EmulationOrientation
import org.yuzu.yuzu_emu.features.settings.model.Settings.EmulationVerticalAlignment
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
import org.yuzu.yuzu_emu.model.DriverViewModel
import org.yuzu.yuzu_emu.model.EmulationViewModel
@ -96,6 +98,7 @@ import java.io.ByteArrayOutputStream
import java.io.File
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import kotlin.or
class EmulationFragment : Fragment(), SurfaceHolder.Callback {
private lateinit var emulationState: EmulationState
@ -136,6 +139,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
private var wasInputOverlayAutoHidden = false
private var overlayTouchActive = false
var shouldUseCustom = false
private var isQuickSettingsMenuOpen = false
private val quickSettings = QuickSettings(this)
private val loadAmiiboLauncher =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
isAmiiboPickerOpen = false
@ -283,7 +290,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
// Normal game launch from arguments
else -> {
val shouldUseCustom = game?.let { it == args.game && args.custom } ?: false
shouldUseCustom = game?.let { it == args.game && args.custom } ?: false
if (shouldUseCustom) {
SettingsFile.loadCustomConfig(game!!)
@ -659,6 +666,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
binding.inGameMenu.requestFocus()
emulationViewModel.setDrawerOpen(true)
updateQuickOverlayMenuEntry(BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean())
if (drawerView == binding.inGameMenu) {
binding.drawerLayout.closeDrawer(binding.quickSettingsSheet)
} else if (drawerView == binding.quickSettingsSheet) {
binding.drawerLayout.closeDrawer(binding.inGameMenu)
}
}
override fun onDrawerClosed(drawerView: View) {
@ -726,16 +738,23 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
Settings.MenuTag.SECTION_ROOT
)
binding.inGameMenu.requestFocus()
binding.drawerLayout.closeDrawer(binding.quickSettingsSheet)
binding.root.findNavController().navigate(action)
true
}
R.id.menu_quick_settings -> {
openQuickSettingsMenu()
true
}
R.id.menu_settings_per_game -> {
val action = HomeNavigationDirections.actionGlobalSettingsActivity(
args.game,
Settings.MenuTag.SECTION_ROOT
)
binding.inGameMenu.requestFocus()
binding.drawerLayout.closeDrawer(binding.quickSettingsSheet)
binding.root.findNavController().navigate(action)
true
}
@ -801,6 +820,36 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
}
addQuickSettings()
binding.drawerLayout.addDrawerListener(object : DrawerListener {
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
// no op
}
override fun onDrawerOpened(drawerView: View) {
if (drawerView == binding.quickSettingsSheet) {
isQuickSettingsMenuOpen = true
if (shouldUseCustom) {
SettingsFile.loadCustomConfig(args.game!!)
}
}
}
override fun onDrawerClosed(drawerView: View) {
if (drawerView == binding.quickSettingsSheet) {
isQuickSettingsMenuOpen = false
if (shouldUseCustom) {
NativeConfig.unloadPerGameConfig()
}
}
}
override fun onDrawerStateChanged(newState: Int) {
// No op
}
})
setInsets()
requireActivity().onBackPressedDispatcher.addCallback(
@ -979,6 +1028,73 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
}
private fun addQuickSettings() {
binding.quickSettingsSheet.apply {
val container = binding.quickSettingsSheet.findViewById<ViewGroup>(R.id.quick_settings_container)
container.removeAllViews()
if (shouldUseCustom) {
quickSettings.addPerGameConfigStatusIndicator(container)
}
quickSettings.addBooleanSetting(
container,
BooleanSetting.RENDERER_USE_SPEED_LIMIT,
)
quickSettings.addSliderSetting(
container,
ShortSetting.RENDERER_SPEED_LIMIT,
minValue = 0,
maxValue = 400,
units = "%",
)
quickSettings.addBooleanSetting(
container,
BooleanSetting.USE_DOCKED_MODE,
)
quickSettings.addDivider(container)
quickSettings.addIntSetting(
container,
IntSetting.RENDERER_ACCURACY,
R.array.rendererAccuracyNames,
R.array.rendererAccuracyValues
)
quickSettings.addIntSetting(
container,
IntSetting.RENDERER_SCALING_FILTER,
R.array.rendererScalingFilterNames,
R.array.rendererScalingFilterValues
)
quickSettings.addSliderSetting(
container,
IntSetting.FSR_SHARPENING_SLIDER,
minValue = 0,
maxValue = 100,
units = "%"
)
quickSettings.addIntSetting(
container,
IntSetting.RENDERER_ANTI_ALIASING,
R.array.rendererAntiAliasingNames,
R.array.rendererAntiAliasingValues
)
}
}
private fun openQuickSettingsMenu() {
binding.drawerLayout.closeDrawer(binding.inGameMenu)
binding.drawerLayout.openDrawer(binding.quickSettingsSheet)
}
private fun updateQuickOverlayMenuEntry(isVisible: Boolean) {
val b = _binding ?: return
val item = b.inGameMenu.menu.findItem(R.id.menu_quick_overlay) ?: return
@ -1151,6 +1267,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
// we need to reinitialize the auto-hide timer
initializeOverlayAutoHide()
addQuickSettings()
}
private fun resetInputOverlay() {
@ -1809,6 +1926,26 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
windowInsets
}
ViewCompat.setOnApplyWindowInsetsListener(binding.quickSettingsSheet) { v, insets ->
val systemBarsInsets: Insets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
if (v.layoutDirection == View.LAYOUT_DIRECTION_LTR) {
v.setPadding(
systemBarsInsets.left,
systemBarsInsets.top,
0,
systemBarsInsets.bottom
)
} else {
v.setPadding(
0,
systemBarsInsets.top,
systemBarsInsets.right,
systemBarsInsets.bottom
)
}
insets
}
}
private class EmulationState(

23
src/android/app/src/main/res/layout/fragment_emulation.xml

@ -171,14 +171,27 @@
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/in_game_menu"
android:id="@+id/quick_settings_sheet"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:layout_gravity="end"
android:focusedByDefault="true"
app:headerLayout="@layout/header_in_game"
app:menu="@menu/menu_in_game"
android:background="?attr/colorSurface"
tools:visibility="gone" />
tools:visibility="gone">
<include layout="@layout/layout_quick_settings" />
</com.google.android.material.navigation.NavigationView>
<com.google.android.material.navigation.NavigationView
android:id="@+id/in_game_menu"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:focusedByDefault="true"
app:headerLayout="@layout/header_in_game"
app:menu="@menu/menu_in_game"
android:background="?attr/colorSurface"
tools:visibility="gone" />
</androidx.drawerlayout.widget.DrawerLayout>

5
src/android/app/src/main/res/layout/item_quick_settings_divider.xml

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider" />

140
src/android/app/src/main/res/layout/item_quick_settings_menu.xml

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/setting_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="24dp"
android:paddingEnd="24dp"
android:paddingTop="12dp"
android:paddingBottom="8dp"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:visibility="gone">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/setting_title"
style="@style/TextAppearance.Material3.TitleSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/setting_value"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textColor="?attr/colorOnSurfaceVariant" />
</LinearLayout>
<ImageView
android:id="@+id/expand_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:src="@drawable/ic_dropdown_arrow"
android:contentDescription=""
app:tint="?attr/colorPrimary" />
</LinearLayout>
<RadioGroup
android:id="@+id/radio_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="24dp"
android:paddingEnd="24dp"
android:paddingBottom="8dp"
android:visibility="gone" />
<LinearLayout
android:id="@+id/slider_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="24dp"
android:paddingEnd="24dp"
android:paddingTop="12dp"
android:paddingBottom="8dp"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/slider_title"
style="@style/TextAppearance.Material3.TitleSmall"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/slider_value_display"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/colorOnSurfaceVariant" />
</LinearLayout>
<com.google.android.material.slider.Slider
android:id="@+id/setting_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:valueFrom="0"
android:valueTo="100"
android:stepSize="1" />
</LinearLayout>
<LinearLayout
android:id="@+id/switch_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="24dp"
android:paddingEnd="24dp"
android:paddingTop="12dp"
android:paddingBottom="8dp"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:visibility="gone">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/switch_title"
style="@style/TextAppearance.Material3.TitleSmall"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/setting_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="48dp" />
</LinearLayout>
</LinearLayout>

37
src/android/app/src/main/res/layout/item_quick_settings_status.xml

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:cardElevation="2dp"
app:cardCornerRadius="12dp"
app:strokeWidth="1dp"
app:strokeColor="?attr/colorPrimary">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:padding="16dp">
<ImageView
android:id="@+id/status_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_settings_outline"
android:contentDescription="" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/status_text"
style="@style/TextAppearance.Material3.TitleSmall"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="12dp"
android:textColor="?attr/colorPrimary" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

34
src/android/app/src/main/res/layout/layout_quick_settings.xml

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/quick_settings_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="0dp"
app:title="@string/quick_settings"
app:titleTextAppearance="@style/TextAppearance.Material3.TitleLarge"
android:fitsSystemWindows="true" />
<LinearLayout
android:id="@+id/quick_settings_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="16dp" />
</LinearLayout>
</ScrollView>

5
src/android/app/src/main/res/menu/menu_in_game.xml

@ -18,6 +18,11 @@
android:icon="@drawable/ic_settings"
android:title="@string/preferences_settings" />
<item
android:id="@+id/menu_quick_settings"
android:icon="@drawable/ic_settings"
android:title="@string/quick_settings" />
<item
android:id="@+id/menu_settings_per_game"
android:icon="@drawable/ic_settings_outline"

2
src/android/app/src/main/res/values/strings.xml

@ -21,6 +21,7 @@
<string name="value_too_high">Value must be at most %1$d</string>
<string name="invalid_value">Invalid value</string>
<string name="using_per_game_config">Using Per-Game Config</string>
<!-- Input Overlay -->
<string name="show_input_overlay">Show Input Overlay</string>
@ -709,6 +710,7 @@
<string name="preferences_system_description">Docked mode, region, language</string>
<string name="preferences_graphics">Graphics</string>
<string name="preferences_graphics_description">Accuracy level, resolution, shader cache</string>
<string name="quick_settings">Quick Settings</string>
<string name="preferences_audio">Audio</string>
<string name="preferences_audio_description">Output engine, volume</string>
<string name="preferences_controls">Controls</string>

Loading…
Cancel
Save