diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt
index 04ab6a220a..9561748cbb 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt
@@ -46,7 +46,7 @@ class YuzuApplication : Application() {
         super.onCreate()
         application = this
         documentsTree = DocumentsTree()
-        DirectoryInitialization.start(applicationContext)
+        DirectoryInitialization.start()
         GpuDriverHelper.initializeDriverParameters(applicationContext)
         NativeLibrary.logDeviceInfo()
 
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
index 6f52a7a8da..dbd602a1d0 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
@@ -85,9 +85,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
 
         val navHostFragment =
             supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
-        val navController = navHostFragment.navController
-        navController
-            .setGraph(R.navigation.emulation_navigation, intent.extras)
+        navHostFragment.navController.setGraph(R.navigation.emulation_navigation, intent.extras)
 
         isActivityRecreated = savedInstanceState != null
 
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
index 733a53c8cf..7fd83f5f7a 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
@@ -3,10 +3,7 @@
 
 package org.yuzu.yuzu_emu.features.settings.ui
 
-import android.content.Context
-import android.content.Intent
 import android.os.Bundle
-import android.view.Menu
 import android.view.View
 import android.view.ViewGroup.MarginLayoutParams
 import android.widget.Toast
@@ -16,20 +13,26 @@ import androidx.appcompat.app.AppCompatActivity
 import androidx.core.view.ViewCompat
 import androidx.core.view.WindowCompat
 import androidx.core.view.WindowInsetsCompat
-import androidx.core.view.updatePadding
+import androidx.navigation.fragment.NavHostFragment
+import androidx.navigation.navArgs
 import com.google.android.material.color.MaterialColors
+import org.yuzu.yuzu_emu.NativeLibrary
 import java.io.IOException
 import org.yuzu.yuzu_emu.R
 import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding
 import org.yuzu.yuzu_emu.features.settings.model.Settings
 import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
+import org.yuzu.yuzu_emu.fragments.ResetSettingsDialogFragment
+import org.yuzu.yuzu_emu.model.SettingsViewModel
 import org.yuzu.yuzu_emu.utils.*
 
-class SettingsActivity : AppCompatActivity(), SettingsActivityView {
-    private val presenter = SettingsActivityPresenter(this)
-
+class SettingsActivity : AppCompatActivity() {
     private lateinit var binding: ActivitySettingsBinding
 
+    private val args by navArgs<SettingsActivityArgs>()
+
+    private val settingsViewModel: SettingsViewModel by viewModels()
+
     override fun onCreate(savedInstanceState: Bundle?) {
         ThemeHelper.setTheme(this)
 
@@ -38,16 +41,17 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
         binding = ActivitySettingsBinding.inflate(layoutInflater)
         setContentView(binding.root)
 
+        settingsViewModel.game = args.game
+
+        val navHostFragment =
+            supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
+        navHostFragment.navController.setGraph(R.navigation.settings_navigation, intent.extras)
+
         WindowCompat.setDecorFitsSystemWindows(window, false)
 
-        val launcher = intent
-        val gameID = launcher.getStringExtra(ARG_GAME_ID)
-        val menuTag = launcher.getStringExtra(ARG_MENU_TAG)
-        presenter.onCreate(savedInstanceState, menuTag!!, gameID!!)
-
-        // Show "Back" button in the action bar for navigation
-        setSupportActionBar(binding.toolbarSettings)
-        supportActionBar!!.setDisplayHomeAsUpEnabled(true)
+        if (savedInstanceState != null) {
+            settingsViewModel.shouldSave = savedInstanceState.getBoolean(KEY_SHOULD_SAVE)
+        }
 
         if (InsetsHelper.getSystemGestureType(applicationContext) !=
             InsetsHelper.GESTURE_NAVIGATION
@@ -63,6 +67,28 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
             )
         }
 
+        settingsViewModel.shouldRecreate.observe(this) {
+            if (it) {
+                settingsViewModel.setShouldRecreate(false)
+                recreate()
+            }
+        }
+        settingsViewModel.shouldNavigateBack.observe(this) {
+            if (it) {
+                settingsViewModel.setShouldNavigateBack(false)
+                navigateBack()
+            }
+        }
+        settingsViewModel.shouldShowResetSettingsDialog.observe(this) {
+            if (it) {
+                settingsViewModel.setShouldShowResetSettingsDialog(false)
+                ResetSettingsDialogFragment().show(
+                    supportFragmentManager,
+                    ResetSettingsDialogFragment.TAG
+                )
+            }
+        }
+
         onBackPressedDispatcher.addCallback(
             this,
             object : OnBackPressedCallback(true) {
@@ -73,34 +99,28 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
         setInsets()
     }
 
-    override fun onSupportNavigateUp(): Boolean {
-        navigateBack()
-        return true
-    }
-
-    private fun navigateBack() {
-        if (supportFragmentManager.backStackEntryCount > 0) {
-            supportFragmentManager.popBackStack()
+    fun navigateBack() {
+        val navHostFragment =
+            supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
+        if (navHostFragment.childFragmentManager.backStackEntryCount > 0) {
+            navHostFragment.navController.popBackStack()
         } else {
             finish()
         }
     }
 
-    override fun onCreateOptionsMenu(menu: Menu): Boolean {
-        val inflater = menuInflater
-        inflater.inflate(R.menu.menu_settings, menu)
-        return true
-    }
-
     override fun onSaveInstanceState(outState: Bundle) {
         // Critical: If super method is not called, rotations will be busted.
         super.onSaveInstanceState(outState)
-        presenter.saveState(outState)
+        outState.putBoolean(KEY_SHOULD_SAVE, settingsViewModel.shouldSave)
     }
 
     override fun onStart() {
         super.onStart()
-        presenter.onStart()
+        // TODO: Load custom settings contextually
+        if (!DirectoryInitialization.areDirectoriesReady) {
+            DirectoryInitialization.start()
+        }
     }
 
     /**
@@ -110,65 +130,21 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
      */
     override fun onStop() {
         super.onStop()
-        presenter.onStop(isFinishing)
-    }
-
-    override fun showSettingsFragment(menuTag: String, addToStack: Boolean, gameId: String) {
-        if (!addToStack && settingsFragment != null) {
-            return
+        if (isFinishing && settingsViewModel.shouldSave) {
+            Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...")
+            Settings.saveSettings()
+            NativeLibrary.reloadSettings()
         }
-
-        val transaction = supportFragmentManager.beginTransaction()
-        if (addToStack) {
-            if (areSystemAnimationsEnabled()) {
-                transaction.setCustomAnimations(
-                    R.anim.anim_settings_fragment_in,
-                    R.anim.anim_settings_fragment_out,
-                    0,
-                    R.anim.anim_pop_settings_fragment_out
-                )
-            }
-            transaction.addToBackStack(null)
-        }
-        transaction.replace(
-            R.id.frame_content,
-            SettingsFragment.newInstance(menuTag, gameId),
-            FRAGMENT_TAG
-        )
-        transaction.commit()
     }
 
-    private fun areSystemAnimationsEnabled(): Boolean {
-        val duration = android.provider.Settings.Global.getFloat(
-            contentResolver,
-            android.provider.Settings.Global.ANIMATOR_DURATION_SCALE,
-            1f
-        )
-        val transition = android.provider.Settings.Global.getFloat(
-            contentResolver,
-            android.provider.Settings.Global.TRANSITION_ANIMATION_SCALE,
-            1f
-        )
-        return duration != 0f && transition != 0f
-    }
-
-    override fun onSettingsFileLoaded() {
-        val fragment: SettingsFragmentView? = settingsFragment
-        fragment?.loadSettingsList()
-    }
-
-    override fun onSettingsFileNotFound() {
-        val fragment: SettingsFragmentView? = settingsFragment
-        fragment?.loadSettingsList()
-    }
-
-    override fun onSettingChanged() {
-        presenter.onSettingChanged()
+    override fun onDestroy() {
+        settingsViewModel.clear()
+        super.onDestroy()
     }
 
     fun onSettingsReset() {
         // Prevents saving to a non-existent settings file
-        presenter.onSettingsReset()
+        settingsViewModel.shouldSave = false
 
         // Delete settings file because the user may have changed values that do not exist in the UI
         val settingsFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_CONFIG)
@@ -185,47 +161,21 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
         finish()
     }
 
-    fun setToolbarTitle(title: String) {
-        binding.toolbarSettingsLayout.title = title
-    }
-
-    private val settingsFragment: SettingsFragment?
-        get() = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as SettingsFragment?
-
     private fun setInsets() {
         ViewCompat.setOnApplyWindowInsetsListener(
-            binding.frameContent
+            binding.navigationBarShade
         ) { view: View, windowInsets: WindowInsetsCompat ->
             val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
-            val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
-            view.updatePadding(
-                left = barInsets.left + cutoutInsets.left,
-                right = barInsets.right + cutoutInsets.right
-            )
 
-            val mlpAppBar = binding.appbarSettings.layoutParams as MarginLayoutParams
-            mlpAppBar.leftMargin = barInsets.left + cutoutInsets.left
-            mlpAppBar.rightMargin = barInsets.right + cutoutInsets.right
-            binding.appbarSettings.layoutParams = mlpAppBar
-
-            val mlpShade = binding.navigationBarShade.layoutParams as MarginLayoutParams
+            val mlpShade = view.layoutParams as MarginLayoutParams
             mlpShade.height = barInsets.bottom
-            binding.navigationBarShade.layoutParams = mlpShade
+            view.layoutParams = mlpShade
 
             windowInsets
         }
     }
 
     companion object {
-        private const val ARG_MENU_TAG = "menu_tag"
-        private const val ARG_GAME_ID = "game_id"
-        private const val FRAGMENT_TAG = "settings"
-
-        fun launch(context: Context, menuTag: String?, gameId: String?) {
-            val settings = Intent(context, SettingsActivity::class.java)
-            settings.putExtra(ARG_MENU_TAG, menuTag)
-            settings.putExtra(ARG_GAME_ID, gameId)
-            context.startActivity(settings)
-        }
+        private const val KEY_SHOULD_SAVE = "should_save"
     }
 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt
deleted file mode 100644
index fdbad32bf1..0000000000
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.yuzu.yuzu_emu.features.settings.ui
-
-import android.content.Context
-import android.os.Bundle
-import java.io.File
-import org.yuzu.yuzu_emu.NativeLibrary
-import org.yuzu.yuzu_emu.features.settings.model.Settings
-import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
-import org.yuzu.yuzu_emu.utils.DirectoryInitialization
-import org.yuzu.yuzu_emu.utils.Log
-
-class SettingsActivityPresenter(private val activityView: SettingsActivityView) {
-    private var shouldSave = false
-    private lateinit var menuTag: String
-    private lateinit var gameId: String
-
-    fun onCreate(savedInstanceState: Bundle?, menuTag: String, gameId: String) {
-        this.menuTag = menuTag
-        this.gameId = gameId
-        if (savedInstanceState != null) {
-            shouldSave = savedInstanceState.getBoolean(KEY_SHOULD_SAVE)
-        }
-    }
-
-    fun onStart() {
-        prepareDirectoriesIfNeeded()
-    }
-
-    private fun loadSettingsUI() {
-        // TODO: Load custom settings contextually
-        activityView.showSettingsFragment(menuTag, false, gameId)
-        activityView.onSettingsFileLoaded()
-    }
-
-    private fun prepareDirectoriesIfNeeded() {
-        val configFile =
-            File(
-                "${DirectoryInitialization.userDirectory}/config/" +
-                    "${SettingsFile.FILE_NAME_CONFIG}.ini"
-            )
-        if (!configFile.exists()) {
-            Log.error(
-                "${DirectoryInitialization.userDirectory}/config/" +
-                    "${SettingsFile.FILE_NAME_CONFIG}.ini"
-            )
-            Log.error("yuzu config file could not be found!")
-        }
-
-        if (!DirectoryInitialization.areDirectoriesReady) {
-            DirectoryInitialization.start(activityView as Context)
-        }
-        loadSettingsUI()
-    }
-
-    fun onStop(finishing: Boolean) {
-        if (finishing && shouldSave) {
-            Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...")
-            Settings.saveSettings()
-            NativeLibrary.reloadSettings()
-        }
-    }
-
-    fun onSettingChanged() {
-        shouldSave = true
-    }
-
-    fun onSettingsReset() {
-        shouldSave = false
-    }
-
-    fun saveState(outState: Bundle) {
-        outState.putBoolean(KEY_SHOULD_SAVE, shouldSave)
-    }
-
-    companion object {
-        private const val KEY_SHOULD_SAVE = "should_save"
-    }
-}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt
deleted file mode 100644
index 07a58b4eaa..0000000000
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.yuzu.yuzu_emu.features.settings.ui
-
-/**
- * Abstraction for the Activity that manages SettingsFragments.
- */
-interface SettingsActivityView {
-    /**
-     * Show a new SettingsFragment.
-     *
-     * @param menuTag    Identifier for the settings group that should be displayed.
-     * @param addToStack Whether or not this fragment should replace a previous one.
-     */
-    fun showSettingsFragment(menuTag: String, addToStack: Boolean, gameId: String)
-
-    /**
-     * Called when a load operation completes.
-     */
-    fun onSettingsFileLoaded()
-
-    /**
-     * Called when a load operation fails.
-     */
-    fun onSettingsFileNotFound()
-
-    /**
-     * End the activity.
-     */
-    fun finish()
-
-    /**
-     * Called by a containing Fragment to tell the Activity that a setting was changed;
-     * unless this has been called, the Activity will not save to disk.
-     */
-    fun onSettingChanged()
-}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt
index 27eaaa576e..9883c2ec70 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt
@@ -12,7 +12,8 @@ import android.view.LayoutInflater
 import android.view.ViewGroup
 import android.widget.TextView
 import androidx.appcompat.app.AlertDialog
-import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.ViewModelProvider
+import androidx.navigation.findNavController
 import androidx.recyclerview.widget.RecyclerView
 import com.google.android.material.datepicker.MaterialDatePicker
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -20,6 +21,7 @@ import com.google.android.material.slider.Slider
 import com.google.android.material.timepicker.MaterialTimePicker
 import com.google.android.material.timepicker.TimeFormat
 import org.yuzu.yuzu_emu.R
+import org.yuzu.yuzu_emu.SettingsNavigationDirections
 import org.yuzu.yuzu_emu.databinding.DialogSliderBinding
 import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
 import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding
@@ -30,18 +32,22 @@ import org.yuzu.yuzu_emu.features.settings.model.FloatSetting
 import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
 import org.yuzu.yuzu_emu.features.settings.model.view.*
 import org.yuzu.yuzu_emu.features.settings.ui.viewholder.*
+import org.yuzu.yuzu_emu.model.SettingsViewModel
 
 class SettingsAdapter(
-    private val fragmentView: SettingsFragmentView,
+    private val fragment: SettingsFragment,
     private val context: Context
 ) : RecyclerView.Adapter<SettingViewHolder?>(), DialogInterface.OnClickListener {
-    private var settings: ArrayList<SettingsItem>? = null
+    private var settings = ArrayList<SettingsItem>()
     private var clickedItem: SettingsItem? = null
     private var clickedPosition: Int
     private var dialog: AlertDialog? = null
     private var sliderProgress = 0
     private var textSliderValue: TextView? = null
 
+    private val settingsViewModel: SettingsViewModel
+        get() = ViewModelProvider(fragment.requireActivity())[SettingsViewModel::class.java]
+
     private var defaultCancelListener =
         DialogInterface.OnClickListener { _: DialogInterface?, _: Int -> closeDialog() }
 
@@ -91,30 +97,22 @@ class SettingsAdapter(
         holder.bind(getItem(position))
     }
 
-    private fun getItem(position: Int): SettingsItem {
-        return settings!![position]
-    }
+    private fun getItem(position: Int): SettingsItem = settings[position]
 
-    override fun getItemCount(): Int {
-        return if (settings != null) {
-            settings!!.size
-        } else {
-            0
-        }
-    }
+    override fun getItemCount(): Int = settings.size
 
     override fun getItemViewType(position: Int): Int {
         return getItem(position).type
     }
 
-    fun setSettingsList(settings: ArrayList<SettingsItem>?) {
+    fun setSettingsList(settings: ArrayList<SettingsItem>) {
         this.settings = settings
         notifyDataSetChanged()
     }
 
     fun onBooleanClick(item: SwitchSetting, position: Int, checked: Boolean) {
         item.checked = checked
-        fragmentView.onSettingChanged()
+        settingsViewModel.shouldSave = true
     }
 
     private fun onSingleChoiceClick(item: SingleChoiceSetting) {
@@ -155,7 +153,7 @@ class SettingsAdapter(
         calendar.timeZone = TimeZone.getTimeZone("UTC")
 
         var timeFormat: Int = TimeFormat.CLOCK_12H
-        if (DateFormat.is24HourFormat(fragmentView.activityView as AppCompatActivity)) {
+        if (DateFormat.is24HourFormat(context)) {
             timeFormat = TimeFormat.CLOCK_24H
         }
 
@@ -172,7 +170,7 @@ class SettingsAdapter(
 
         datePicker.addOnPositiveButtonClickListener {
             timePicker.show(
-                (fragmentView.activityView as AppCompatActivity).supportFragmentManager,
+                fragment.childFragmentManager,
                 "TimePicker"
             )
         }
@@ -181,14 +179,14 @@ class SettingsAdapter(
             epochTime += timePicker.hour.toLong() * 60 * 60
             epochTime += timePicker.minute.toLong() * 60
             if (item.value != epochTime) {
-                fragmentView.onSettingChanged()
+                settingsViewModel.shouldSave = true
                 notifyItemChanged(clickedPosition)
                 item.value = epochTime
             }
             clickedItem = null
         }
         datePicker.show(
-            (fragmentView.activityView as AppCompatActivity).supportFragmentManager,
+            fragment.childFragmentManager,
             "DatePicker"
         )
     }
@@ -231,7 +229,8 @@ class SettingsAdapter(
     }
 
     fun onSubmenuClick(item: SubmenuSetting) {
-        fragmentView.loadSubMenu(item.menuKey)
+        val action = SettingsNavigationDirections.actionGlobalSettingsFragment(item.menuKey, null)
+        fragment.view?.findNavController()?.navigate(action)
     }
 
     override fun onClick(dialog: DialogInterface, which: Int) {
@@ -240,7 +239,7 @@ class SettingsAdapter(
                 val scSetting = clickedItem as SingleChoiceSetting
                 val value = getValueForSingleChoiceSelection(scSetting, which)
                 if (scSetting.selectedValue != value) {
-                    fragmentView.onSettingChanged()
+                    settingsViewModel.shouldSave = true
                 }
 
                 // Get the backing Setting, which may be null (if for example it was missing from the file)
@@ -251,7 +250,7 @@ class SettingsAdapter(
             is StringSingleChoiceSetting -> {
                 val scSetting = clickedItem as StringSingleChoiceSetting
                 val value = scSetting.getValueAt(which)
-                if (scSetting.selectedValue != value) fragmentView.onSettingChanged()
+                if (scSetting.selectedValue != value) settingsViewModel.shouldSave = true
                 scSetting.selectedValue = value!!
                 closeDialog()
             }
@@ -259,7 +258,7 @@ class SettingsAdapter(
             is SliderSetting -> {
                 val sliderSetting = clickedItem as SliderSetting
                 if (sliderSetting.selectedValue != sliderProgress) {
-                    fragmentView.onSettingChanged()
+                    settingsViewModel.shouldSave = true
                 }
                 when (sliderSetting.setting) {
                     is ByteSetting -> {
@@ -294,7 +293,7 @@ class SettingsAdapter(
             .setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
                 setting.reset()
                 notifyItemChanged(position)
-                fragmentView.onSettingChanged()
+                settingsViewModel.shouldSave = true
             }
             .setNegativeButton(android.R.string.cancel, null)
             .show()
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt
index dc1bf6eb1d..de6aebd9df 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt
@@ -3,39 +3,41 @@
 
 package org.yuzu.yuzu_emu.features.settings.ui
 
-import android.content.Context
 import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.view.ViewGroup.MarginLayoutParams
 import androidx.core.view.ViewCompat
 import androidx.core.view.WindowInsetsCompat
 import androidx.core.view.updatePadding
 import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.navigation.fragment.navArgs
 import androidx.recyclerview.widget.LinearLayoutManager
 import com.google.android.material.divider.MaterialDividerItemDecoration
+import com.google.android.material.transition.MaterialSharedAxis
+import org.yuzu.yuzu_emu.R
 import org.yuzu.yuzu_emu.databinding.FragmentSettingsBinding
-import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
+import org.yuzu.yuzu_emu.model.SettingsViewModel
 
-class SettingsFragment : Fragment(), SettingsFragmentView {
-    override var activityView: SettingsActivityView? = null
-
-    private val fragmentPresenter = SettingsFragmentPresenter(this)
+class SettingsFragment : Fragment() {
+    private lateinit var presenter: SettingsFragmentPresenter
     private var settingsAdapter: SettingsAdapter? = null
 
     private var _binding: FragmentSettingsBinding? = null
     private val binding get() = _binding!!
 
-    override fun onAttach(context: Context) {
-        super.onAttach(context)
-        activityView = requireActivity() as SettingsActivityView
-    }
+    private val args by navArgs<SettingsFragmentArgs>()
+
+    private val settingsViewModel: SettingsViewModel by activityViewModels()
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        val menuTag = requireArguments().getString(ARGUMENT_MENU_TAG)
-        val gameId = requireArguments().getString(ARGUMENT_GAME_ID)
-        fragmentPresenter.onCreate(menuTag!!, gameId!!)
+        enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
+        returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
+        reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
+        exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
     }
 
     override fun onCreateView(
@@ -48,7 +50,14 @@ class SettingsFragment : Fragment(), SettingsFragmentView {
     }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        settingsAdapter = SettingsAdapter(this, requireActivity())
+        settingsAdapter = SettingsAdapter(this, requireContext())
+        presenter = SettingsFragmentPresenter(
+            settingsViewModel,
+            settingsAdapter!!,
+            args.menuTag,
+            args.game?.gameId ?: ""
+        )
+
         val dividerDecoration = MaterialDividerItemDecoration(
             requireContext(),
             LinearLayoutManager.VERTICAL
@@ -56,63 +65,52 @@ class SettingsFragment : Fragment(), SettingsFragmentView {
         dividerDecoration.isLastItemDecorated = false
         binding.listSettings.apply {
             adapter = settingsAdapter
-            layoutManager = LinearLayoutManager(activity)
+            layoutManager = LinearLayoutManager(requireContext())
             addItemDecoration(dividerDecoration)
         }
-        fragmentPresenter.onViewCreated()
+
+        binding.toolbarSettings.setNavigationOnClickListener {
+            settingsViewModel.setShouldNavigateBack(true)
+        }
+
+        settingsViewModel.toolbarTitle.observe(viewLifecycleOwner) {
+            if (it.isNotEmpty()) binding.toolbarSettingsLayout.title = it
+        }
+
+        presenter.onViewCreated()
 
         setInsets()
     }
 
     override fun onDetach() {
         super.onDetach()
-        activityView = null
-        if (settingsAdapter != null) {
-            settingsAdapter!!.closeDialog()
-        }
-    }
-
-    override fun showSettingsList(settingsList: ArrayList<SettingsItem>) {
-        settingsAdapter!!.setSettingsList(settingsList)
-    }
-
-    override fun loadSettingsList() {
-        fragmentPresenter.loadSettingsList()
-    }
-
-    override fun loadSubMenu(menuKey: String) {
-        activityView!!.showSettingsFragment(
-            menuKey,
-            true,
-            requireArguments().getString(ARGUMENT_GAME_ID)!!
-        )
-    }
-
-    override fun onSettingChanged() {
-        activityView!!.onSettingChanged()
+        settingsAdapter?.closeDialog()
     }
 
     private fun setInsets() {
         ViewCompat.setOnApplyWindowInsetsListener(
-            binding.listSettings
-        ) { view: View, windowInsets: WindowInsetsCompat ->
-            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
-            view.updatePadding(bottom = insets.bottom)
+            binding.root
+        ) { _: View, windowInsets: WindowInsetsCompat ->
+            val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+            val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
+
+            val leftInsets = barInsets.left + cutoutInsets.left
+            val rightInsets = barInsets.right + cutoutInsets.right
+
+            val sideMargin = resources.getDimensionPixelSize(R.dimen.spacing_medlarge)
+            val mlpSettingsList = binding.listSettings.layoutParams as MarginLayoutParams
+            mlpSettingsList.leftMargin = sideMargin + leftInsets
+            mlpSettingsList.rightMargin = sideMargin + rightInsets
+            binding.listSettings.layoutParams = mlpSettingsList
+            binding.listSettings.updatePadding(
+                bottom = barInsets.bottom
+            )
+
+            val mlpAppBar = binding.appbarSettings.layoutParams as MarginLayoutParams
+            mlpAppBar.leftMargin = leftInsets
+            mlpAppBar.rightMargin = rightInsets
+            binding.appbarSettings.layoutParams = mlpAppBar
             windowInsets
         }
     }
-
-    companion object {
-        private const val ARGUMENT_MENU_TAG = "menu_tag"
-        private const val ARGUMENT_GAME_ID = "game_id"
-
-        fun newInstance(menuTag: String?, gameId: String?): Fragment {
-            val fragment = SettingsFragment()
-            val arguments = Bundle()
-            arguments.putString(ARGUMENT_MENU_TAG, menuTag)
-            arguments.putString(ARGUMENT_GAME_ID, gameId)
-            fragment.arguments = arguments
-            return fragment
-        }
-    }
 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
index dddbf65bb7..ba45c317dd 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -3,6 +3,7 @@
 
 package org.yuzu.yuzu_emu.features.settings.ui
 
+import android.content.Context
 import android.content.SharedPreferences
 import android.os.Build
 import android.text.TextUtils
@@ -20,36 +21,36 @@ import org.yuzu.yuzu_emu.features.settings.model.Settings
 import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
 import org.yuzu.yuzu_emu.features.settings.model.view.*
 import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
-import org.yuzu.yuzu_emu.fragments.ResetSettingsDialogFragment
-import org.yuzu.yuzu_emu.utils.ThemeHelper
+import org.yuzu.yuzu_emu.model.SettingsViewModel
 
-class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) {
-    private var menuTag: String? = null
-    private lateinit var gameId: String
-    private var settingsList: ArrayList<SettingsItem>? = null
+class SettingsFragmentPresenter(
+    private val settingsViewModel: SettingsViewModel,
+    private val adapter: SettingsAdapter,
+    private var menuTag: String,
+    private var gameId: String
+) {
+    private var settingsList = ArrayList<SettingsItem>()
 
-    private val settingsActivity get() = fragmentView.activityView as SettingsActivity
+    private val preferences: SharedPreferences
+        get() = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
 
-    private lateinit var preferences: SharedPreferences
-
-    fun onCreate(menuTag: String, gameId: String) {
-        this.gameId = gameId
-        this.menuTag = menuTag
-    }
+    private val context: Context get() = YuzuApplication.appContext
 
     fun onViewCreated() {
-        preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
         loadSettingsList()
     }
 
-    fun loadSettingsList() {
+    private fun loadSettingsList() {
         if (!TextUtils.isEmpty(gameId)) {
-            settingsActivity.setToolbarTitle("Game Settings: $gameId")
+            settingsViewModel.setToolbarTitle(
+                context.getString(
+                    R.string.advanced_settings_game,
+                    gameId
+                )
+            )
         }
+
         val sl = ArrayList<SettingsItem>()
-        if (menuTag == null) {
-            return
-        }
         when (menuTag) {
             SettingsFile.FILE_NAME_CONFIG -> addConfigSettings(sl)
             Settings.SECTION_GENERAL -> addGeneralSettings(sl)
@@ -69,11 +70,11 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
             }
         }
         settingsList = sl
-        fragmentView.showSettingsList(settingsList!!)
+        adapter.setSettingsList(settingsList)
     }
 
     private fun addConfigSettings(sl: ArrayList<SettingsItem>) {
-        settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.advanced_settings))
+        settingsViewModel.setToolbarTitle(context.getString(R.string.advanced_settings))
         sl.apply {
             add(SubmenuSetting(R.string.preferences_general, 0, Settings.SECTION_GENERAL))
             add(SubmenuSetting(R.string.preferences_system, 0, Settings.SECTION_SYSTEM))
@@ -82,17 +83,14 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
             add(SubmenuSetting(R.string.preferences_debug, 0, Settings.SECTION_DEBUG))
             add(
                 RunnableSetting(R.string.reset_to_default, 0, false) {
-                    ResetSettingsDialogFragment().show(
-                        settingsActivity.supportFragmentManager,
-                        ResetSettingsDialogFragment.TAG
-                    )
+                    settingsViewModel.setShouldShowResetSettingsDialog(true)
                 }
             )
         }
     }
 
     private fun addGeneralSettings(sl: ArrayList<SettingsItem>) {
-        settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_general))
+        settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_general))
         sl.apply {
             add(
                 SwitchSetting(
@@ -131,7 +129,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
     }
 
     private fun addSystemSettings(sl: ArrayList<SettingsItem>) {
-        settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_system))
+        settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_system))
         sl.apply {
             add(
                 SwitchSetting(
@@ -170,7 +168,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
     }
 
     private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) {
-        settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_graphics))
+        settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_graphics))
         sl.apply {
             add(
                 SingleChoiceSetting(
@@ -267,7 +265,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
     }
 
     private fun addAudioSettings(sl: ArrayList<SettingsItem>) {
-        settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_audio))
+        settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_audio))
         sl.apply {
             add(
                 SingleChoiceSetting(
@@ -292,7 +290,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
     }
 
     private fun addThemeSettings(sl: ArrayList<SettingsItem>) {
-        settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_theme))
+        settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_theme))
         sl.apply {
             val theme: AbstractIntSetting = object : AbstractIntSetting {
                 override val int: Int
@@ -302,7 +300,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
                     preferences.edit()
                         .putInt(Settings.PREF_THEME, value)
                         .apply()
-                    settingsActivity.recreate()
+                    settingsViewModel.setShouldRecreate(true)
                 }
 
                 override val key: String? = null
@@ -346,7 +344,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
                     preferences.edit()
                         .putInt(Settings.PREF_THEME_MODE, value)
                         .apply()
-                    ThemeHelper.setThemeMode(settingsActivity)
+                    settingsViewModel.setShouldRecreate(true)
                 }
 
                 override val key: String? = null
@@ -357,6 +355,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
                     preferences.edit()
                         .putInt(Settings.PREF_BLACK_BACKGROUNDS, defaultValue)
                         .apply()
+                    settingsViewModel.setShouldRecreate(true)
                 }
             }
 
@@ -378,7 +377,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
                     preferences.edit()
                         .putBoolean(Settings.PREF_BLACK_BACKGROUNDS, value)
                         .apply()
-                    settingsActivity.recreate()
+                    settingsViewModel.setShouldRecreate(true)
                 }
 
                 override val key: String? = null
@@ -389,6 +388,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
                     preferences.edit()
                         .putBoolean(Settings.PREF_BLACK_BACKGROUNDS, defaultValue)
                         .apply()
+                    settingsViewModel.setShouldRecreate(true)
                 }
             }
 
@@ -403,7 +403,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
     }
 
     private fun addDebugSettings(sl: ArrayList<SettingsItem>) {
-        settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_debug))
+        settingsViewModel.setToolbarTitle(context.getString(R.string.preferences_debug))
         sl.apply {
             add(HeaderSetting(R.string.gpu))
             add(
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt
deleted file mode 100644
index a4d7a80aac..0000000000
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.yuzu.yuzu_emu.features.settings.ui
-
-import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
-
-/**
- * Abstraction for a screen showing a list of settings. Instances of
- * this type of view will each display a layer of the setting hierarchy.
- */
-interface SettingsFragmentView {
-    /**
-     * Pass an ArrayList to the View so that it can be displayed on screen.
-     *
-     * @param settingsList The result of converting the HashMap to an ArrayList
-     */
-    fun showSettingsList(settingsList: ArrayList<SettingsItem>)
-
-    /**
-     * Instructs the Fragment to load the settings screen.
-     */
-    fun loadSettingsList()
-
-    /**
-     * @return The Fragment's containing activity.
-     */
-    val activityView: SettingsActivityView?
-
-    /**
-     * Tell the Fragment to tell the containing Activity to show a new
-     * Fragment containing a submenu of settings.
-     *
-     * @param menuKey Identifier for the settings group that should be shown.
-     */
-    fun loadSubMenu(menuKey: String)
-
-    /**
-     * Have the fragment tell the containing Activity that a setting was modified.
-     */
-    fun onSettingChanged()
-}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
index 09e93a017e..70df3af802 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
@@ -28,6 +28,7 @@ import androidx.fragment.app.Fragment
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
+import androidx.navigation.findNavController
 import androidx.navigation.fragment.navArgs
 import androidx.preference.PreferenceManager
 import androidx.window.layout.FoldingFeature
@@ -37,6 +38,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import com.google.android.material.slider.Slider
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
+import org.yuzu.yuzu_emu.HomeNavigationDirections
 import org.yuzu.yuzu_emu.NativeLibrary
 import org.yuzu.yuzu_emu.R
 import org.yuzu.yuzu_emu.YuzuApplication
@@ -45,7 +47,6 @@ import org.yuzu.yuzu_emu.databinding.DialogOverlayAdjustBinding
 import org.yuzu.yuzu_emu.databinding.FragmentEmulationBinding
 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.ui.SettingsActivity
 import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
 import org.yuzu.yuzu_emu.overlay.InputOverlay
 import org.yuzu.yuzu_emu.utils.*
@@ -139,7 +140,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
                 }
 
                 R.id.menu_settings -> {
-                    SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "")
+                    val action = HomeNavigationDirections.actionGlobalSettingsActivity(
+                        null,
+                        SettingsFile.FILE_NAME_CONFIG
+                    )
+                    binding.root.findNavController().navigate(action)
                     true
                 }
 
@@ -211,7 +216,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
     override fun onResume() {
         super.onResume()
         if (!DirectoryInitialization.areDirectoriesReady) {
-            DirectoryInitialization.start(requireContext())
+            DirectoryInitialization.start()
         }
 
         updateScreenLayout()
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
index d5e7934915..cbbe14d220 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
@@ -25,17 +25,18 @@ import androidx.core.view.updatePadding
 import androidx.documentfile.provider.DocumentFile
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
+import androidx.navigation.findNavController
 import androidx.navigation.fragment.findNavController
 import androidx.recyclerview.widget.LinearLayoutManager
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import com.google.android.material.transition.MaterialSharedAxis
 import org.yuzu.yuzu_emu.BuildConfig
+import org.yuzu.yuzu_emu.HomeNavigationDirections
 import org.yuzu.yuzu_emu.R
 import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter
 import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding
 import org.yuzu.yuzu_emu.features.DocumentProvider
 import org.yuzu.yuzu_emu.features.settings.model.Settings
-import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity
 import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
 import org.yuzu.yuzu_emu.model.HomeSetting
 import org.yuzu.yuzu_emu.model.HomeViewModel
@@ -74,7 +75,13 @@ class HomeSettingsFragment : Fragment() {
                     R.string.advanced_settings,
                     R.string.settings_description,
                     R.drawable.ic_settings,
-                    { SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "") }
+                    {
+                        val action = HomeNavigationDirections.actionGlobalSettingsActivity(
+                            null,
+                            SettingsFile.FILE_NAME_CONFIG
+                        )
+                        binding.root.findNavController().navigate(action)
+                    }
                 )
             )
             add(
@@ -90,7 +97,13 @@ class HomeSettingsFragment : Fragment() {
                     R.string.preferences_theme,
                     R.string.theme_and_color_description,
                     R.drawable.ic_palette,
-                    { SettingsActivity.launch(requireContext(), Settings.SECTION_THEME, "") }
+                    {
+                        val action = HomeNavigationDirections.actionGlobalSettingsActivity(
+                            null,
+                            Settings.SECTION_THEME
+                        )
+                        binding.root.findNavController().navigate(action)
+                    }
                 )
             )
             add(
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SettingsViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SettingsViewModel.kt
new file mode 100644
index 0000000000..1763341e20
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SettingsViewModel.kt
@@ -0,0 +1,47 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.yuzu.yuzu_emu.model
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+
+class SettingsViewModel : ViewModel() {
+    var game: Game? = null
+
+    var shouldSave = false
+
+    private val _toolbarTitle = MutableLiveData("")
+    val toolbarTitle: LiveData<String> get() = _toolbarTitle
+
+    private val _shouldRecreate = MutableLiveData(false)
+    val shouldRecreate: LiveData<Boolean> get() = _shouldRecreate
+
+    private val _shouldNavigateBack = MutableLiveData(false)
+    val shouldNavigateBack: LiveData<Boolean> get() = _shouldNavigateBack
+
+    private val _shouldShowResetSettingsDialog = MutableLiveData(false)
+    val shouldShowResetSettingsDialog: LiveData<Boolean> get() = _shouldShowResetSettingsDialog
+
+    fun setToolbarTitle(value: String) {
+        _toolbarTitle.value = value
+    }
+
+    fun setShouldRecreate(value: Boolean) {
+        _shouldRecreate.value = value
+    }
+
+    fun setShouldNavigateBack(value: Boolean) {
+        _shouldNavigateBack.value = value
+    }
+
+    fun setShouldShowResetSettingsDialog(value: Boolean) {
+        _shouldShowResetSettingsDialog.value = value
+    }
+
+    fun clear() {
+        game = null
+        shouldSave = false
+    }
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
index d8dbf1f45f..7735452e51 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
@@ -33,13 +33,13 @@ import java.io.IOException
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
+import org.yuzu.yuzu_emu.HomeNavigationDirections
 import org.yuzu.yuzu_emu.NativeLibrary
 import org.yuzu.yuzu_emu.R
 import org.yuzu.yuzu_emu.activities.EmulationActivity
 import org.yuzu.yuzu_emu.databinding.ActivityMainBinding
 import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
 import org.yuzu.yuzu_emu.features.settings.model.Settings
-import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity
 import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
 import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment
 import org.yuzu.yuzu_emu.fragments.LongMessageDialogFragment
@@ -105,11 +105,13 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
             when (it.itemId) {
                 R.id.gamesFragment -> gamesViewModel.setShouldScrollToTop(true)
                 R.id.searchFragment -> gamesViewModel.setSearchFocused(true)
-                R.id.homeSettingsFragment -> SettingsActivity.launch(
-                    this,
-                    SettingsFile.FILE_NAME_CONFIG,
-                    ""
-                )
+                R.id.homeSettingsFragment -> {
+                    val action = HomeNavigationDirections.actionGlobalSettingsActivity(
+                        null,
+                        SettingsFile.FILE_NAME_CONFIG
+                    )
+                    navHostFragment.navController.navigate(action)
+                }
             }
         }
 
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt
index 2ee63697eb..3c9f6bad0f 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt
@@ -3,18 +3,18 @@
 
 package org.yuzu.yuzu_emu.utils
 
-import android.content.Context
 import java.io.IOException
 import org.yuzu.yuzu_emu.NativeLibrary
+import org.yuzu.yuzu_emu.YuzuApplication
 
 object DirectoryInitialization {
     private var userPath: String? = null
 
     var areDirectoriesReady: Boolean = false
 
-    fun start(context: Context) {
+    fun start() {
         if (!areDirectoriesReady) {
-            initializeInternalStorage(context)
+            initializeInternalStorage()
             NativeLibrary.initializeEmulation()
             areDirectoriesReady = true
         }
@@ -26,9 +26,9 @@ object DirectoryInitialization {
             return userPath
         }
 
-    private fun initializeInternalStorage(context: Context) {
+    private fun initializeInternalStorage() {
         try {
-            userPath = context.getExternalFilesDir(null)!!.canonicalPath
+            userPath = YuzuApplication.appContext.getExternalFilesDir(null)!!.canonicalPath
             NativeLibrary.setAppDirectory(userPath!!)
         } catch (e: IOException) {
             e.printStackTrace()
diff --git a/src/android/app/src/main/res/anim-ldrtl/anim_pop_settings_fragment_out.xml b/src/android/app/src/main/res/anim-ldrtl/anim_pop_settings_fragment_out.xml
deleted file mode 100644
index 9f49c133a0..0000000000
--- a/src/android/app/src/main/res/anim-ldrtl/anim_pop_settings_fragment_out.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <alpha
-        android:duration="125"
-        android:interpolator="@android:anim/decelerate_interpolator"
-        android:fromAlpha="1"
-        android:toAlpha="0" />
-
-    <translate
-        android:duration="125"
-        android:interpolator="@android:anim/decelerate_interpolator"
-        android:fromXDelta="0"
-        android:toXDelta="-75" />
-
-</set>
diff --git a/src/android/app/src/main/res/anim-ldrtl/anim_settings_fragment_in.xml b/src/android/app/src/main/res/anim-ldrtl/anim_settings_fragment_in.xml
deleted file mode 100644
index 82fd719dba..0000000000
--- a/src/android/app/src/main/res/anim-ldrtl/anim_settings_fragment_in.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <alpha
-        android:duration="@android:integer/config_shortAnimTime"
-        android:interpolator="@android:anim/decelerate_interpolator"
-        android:fromAlpha="0"
-        android:toAlpha="1" />
-
-    <translate
-        android:duration="@android:integer/config_shortAnimTime"
-        android:interpolator="@android:anim/decelerate_interpolator"
-        android:fromXDelta="-200"
-        android:toXDelta="0" />
-
-</set>
diff --git a/src/android/app/src/main/res/anim/anim_pop_settings_fragment_out.xml b/src/android/app/src/main/res/anim/anim_pop_settings_fragment_out.xml
deleted file mode 100644
index 5892128f18..0000000000
--- a/src/android/app/src/main/res/anim/anim_pop_settings_fragment_out.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <alpha
-        android:duration="125"
-        android:interpolator="@android:anim/decelerate_interpolator"
-        android:fromAlpha="1"
-        android:toAlpha="0" />
-
-    <translate
-        android:duration="125"
-        android:interpolator="@android:anim/decelerate_interpolator"
-        android:fromXDelta="0"
-        android:toXDelta="75" />
-
-</set>
diff --git a/src/android/app/src/main/res/anim/anim_settings_fragment_in.xml b/src/android/app/src/main/res/anim/anim_settings_fragment_in.xml
deleted file mode 100644
index 98e0cf8bd6..0000000000
--- a/src/android/app/src/main/res/anim/anim_settings_fragment_in.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <alpha
-        android:duration="@android:integer/config_shortAnimTime"
-        android:interpolator="@android:anim/decelerate_interpolator"
-        android:fromAlpha="0"
-        android:toAlpha="1" />
-
-    <translate
-        android:duration="@android:integer/config_shortAnimTime"
-        android:interpolator="@android:anim/decelerate_interpolator"
-        android:fromXDelta="200"
-        android:toXDelta="0" />
-
-</set>
diff --git a/src/android/app/src/main/res/anim/anim_settings_fragment_out.xml b/src/android/app/src/main/res/anim/anim_settings_fragment_out.xml
deleted file mode 100644
index 77a40a4d1b..0000000000
--- a/src/android/app/src/main/res/anim/anim_settings_fragment_out.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <alpha
-        android:duration="@android:integer/config_shortAnimTime"
-        android:interpolator="@android:anim/decelerate_interpolator"
-        android:fromAlpha="1"
-        android:toAlpha="0" />
-
-</set>
diff --git a/src/android/app/src/main/res/animator/menu_slide_in_from_start.xml b/src/android/app/src/main/res/animator/menu_slide_in_from_start.xml
deleted file mode 100644
index 4612aee134..0000000000
--- a/src/android/app/src/main/res/animator/menu_slide_in_from_start.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <objectAnimator
-        android:propertyName="translationX"
-        android:valueType="floatType"
-        android:valueFrom="-1280dp"
-        android:valueTo="0"
-        android:interpolator="@android:interpolator/decelerate_quad"
-        android:duration="300"/>
-
-    <objectAnimator
-        android:propertyName="alpha"
-        android:valueType="floatType"
-        android:valueFrom="0"
-        android:valueTo="1"
-        android:interpolator="@android:interpolator/accelerate_quad"
-        android:duration="300"/>
-
-</set>
\ No newline at end of file
diff --git a/src/android/app/src/main/res/animator/menu_slide_out_to_start.xml b/src/android/app/src/main/res/animator/menu_slide_out_to_start.xml
deleted file mode 100644
index c004789466..0000000000
--- a/src/android/app/src/main/res/animator/menu_slide_out_to_start.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <!-- This animation is used ONLY when a submenu is replaced. -->
-    <objectAnimator
-        android:propertyName="translationX"
-        android:valueType="floatType"
-        android:valueFrom="0"
-        android:valueTo="-1280dp"
-        android:interpolator="@android:interpolator/decelerate_quad"
-        android:duration="200"/>
-
-    <objectAnimator
-        android:propertyName="alpha"
-        android:valueType="floatType"
-        android:valueFrom="1"
-        android:valueTo="0"
-        android:interpolator="@android:interpolator/decelerate_quad"
-        android:duration="200"/>
-
-</set>
\ No newline at end of file
diff --git a/src/android/app/src/main/res/layout/activity_settings.xml b/src/android/app/src/main/res/layout/activity_settings.xml
index 14ae83b041..8a026a30ac 100644
--- a/src/android/app/src/main/res/layout/activity_settings.xml
+++ b/src/android/app/src/main/res/layout/activity_settings.xml
@@ -1,42 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
-<androidx.coordinatorlayout.widget.CoordinatorLayout
-    android:id="@+id/coordinator_main"
+<androidx.constraintlayout.widget.ConstraintLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/constraint_settings"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="?attr/colorSurface">
 
-    <com.google.android.material.appbar.AppBarLayout
-        android:id="@+id/appbar_settings"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:fitsSystemWindows="true"
-        app:elevation="0dp">
-
-        <com.google.android.material.appbar.CollapsingToolbarLayout
-            style="?attr/collapsingToolbarLayoutMediumStyle"
-            android:id="@+id/toolbar_settings_layout"
-            android:layout_width="match_parent"
-            android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
-            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
-
-            <com.google.android.material.appbar.MaterialToolbar
-                android:id="@+id/toolbar_settings"
-                android:layout_width="match_parent"
-                android:layout_height="?attr/actionBarSize"
-                app:layout_collapseMode="pin" />
-
-        </com.google.android.material.appbar.CollapsingToolbarLayout>
-
-    </com.google.android.material.appbar.AppBarLayout>
-
-    <FrameLayout
-        android:id="@+id/frame_content"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginHorizontal="12dp"
-        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+    <androidx.fragment.app.FragmentContainerView
+        android:id="@+id/fragment_container"
+        android:name="androidx.navigation.fragment.NavHostFragment"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:defaultNavHost="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:layout="@layout/fragment_settings" />
 
     <View
         android:id="@+id/navigation_bar_shade"
@@ -45,6 +27,8 @@
         android:background="@android:color/transparent"
         android:clickable="false"
         android:focusable="false"
-        android:layout_gravity="bottom|center_horizontal" />
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
 
-</androidx.coordinatorlayout.widget.CoordinatorLayout>
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/src/android/app/src/main/res/layout/fragment_settings.xml b/src/android/app/src/main/res/layout/fragment_settings.xml
index 1677203476..ebedbf1ec4 100644
--- a/src/android/app/src/main/res/layout/fragment_settings.xml
+++ b/src/android/app/src/main/res/layout/fragment_settings.xml
@@ -1,14 +1,41 @@
 <?xml version="1.0" encoding="utf-8"?>
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/coordinator_main"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:background="?attr/colorSurface">
+
+    <com.google.android.material.appbar.AppBarLayout
+        android:id="@+id/appbar_settings"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:fitsSystemWindows="true"
+        app:elevation="0dp">
+
+        <com.google.android.material.appbar.CollapsingToolbarLayout
+            android:id="@+id/toolbar_settings_layout"
+            style="?attr/collapsingToolbarLayoutMediumStyle"
+            android:layout_width="match_parent"
+            android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
+            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
+
+            <com.google.android.material.appbar.MaterialToolbar
+                android:id="@+id/toolbar_settings"
+                android:layout_width="match_parent"
+                android:layout_height="?attr/actionBarSize"
+                app:layout_collapseMode="pin"
+                app:navigationIcon="@drawable/ic_back" />
+
+        </com.google.android.material.appbar.CollapsingToolbarLayout>
+
+    </com.google.android.material.appbar.AppBarLayout>
 
     <androidx.recyclerview.widget.RecyclerView
         android:id="@+id/list_settings"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="?attr/colorSurface"
-        android:clipToPadding="false" />
+        android:clipToPadding="false"
+        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
 
-</FrameLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/src/android/app/src/main/res/menu/menu_settings.xml b/src/android/app/src/main/res/menu/menu_settings.xml
deleted file mode 100644
index 1fe7aa6d4c..0000000000
--- a/src/android/app/src/main/res/menu/menu_settings.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu />
\ No newline at end of file
diff --git a/src/android/app/src/main/res/navigation/emulation_navigation.xml b/src/android/app/src/main/res/navigation/emulation_navigation.xml
index 8208f4c2c4..2a3c23d554 100644
--- a/src/android/app/src/main/res/navigation/emulation_navigation.xml
+++ b/src/android/app/src/main/res/navigation/emulation_navigation.xml
@@ -15,4 +15,21 @@
             app:argType="org.yuzu.yuzu_emu.model.Game" />
     </fragment>
 
+    <activity
+        android:id="@+id/settingsActivity"
+        android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity"
+        android:label="SettingsActivity">
+        <argument
+            android:name="game"
+            app:argType="org.yuzu.yuzu_emu.model.Game"
+            app:nullable="true" />
+        <argument
+            android:name="menuTag"
+            app:argType="string" />
+    </activity>
+
+    <action
+        android:id="@+id/action_global_settingsActivity"
+        app:destination="@id/settingsActivity" />
+
 </navigation>
diff --git a/src/android/app/src/main/res/navigation/home_navigation.xml b/src/android/app/src/main/res/navigation/home_navigation.xml
index fcebba7266..fb8e14448c 100644
--- a/src/android/app/src/main/res/navigation/home_navigation.xml
+++ b/src/android/app/src/main/res/navigation/home_navigation.xml
@@ -70,4 +70,21 @@
         app:destination="@id/emulationActivity"
         app:launchSingleTop="true" />
 
+    <activity
+        android:id="@+id/settingsActivity"
+        android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity"
+        android:label="SettingsActivity">
+        <argument
+            android:name="game"
+            app:argType="org.yuzu.yuzu_emu.model.Game"
+            app:nullable="true" />
+        <argument
+            android:name="menuTag"
+            app:argType="string" />
+    </activity>
+
+    <action
+        android:id="@+id/action_global_settingsActivity"
+        app:destination="@id/settingsActivity" />
+
 </navigation>
diff --git a/src/android/app/src/main/res/navigation/settings_navigation.xml b/src/android/app/src/main/res/navigation/settings_navigation.xml
new file mode 100644
index 0000000000..b36200c655
--- /dev/null
+++ b/src/android/app/src/main/res/navigation/settings_navigation.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<navigation xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/settings_navigation"
+    app:startDestination="@id/settingsFragment">
+
+    <fragment
+        android:id="@+id/settingsFragment"
+        android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsFragment"
+        android:label="SettingsFragment">
+        <argument
+            android:name="menuTag"
+            app:argType="string" />
+        <argument
+            android:name="game"
+            app:argType="org.yuzu.yuzu_emu.model.Game"
+            app:nullable="true" />
+    </fragment>
+
+    <action
+        android:id="@+id/action_global_settingsFragment"
+        app:destination="@id/settingsFragment" />
+
+</navigation>
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index df76563fc2..6b782780a1 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -74,6 +74,7 @@
     <string name="install_gpu_driver">Install GPU driver</string>
     <string name="install_gpu_driver_description">Install alternative drivers for potentially better performance or accuracy</string>
     <string name="advanced_settings">Advanced settings</string>
+    <string name="advanced_settings_game">Advanced settings: %1$s</string>
     <string name="settings_description">Configure emulator settings</string>
     <string name="search_recently_played">Recently played</string>
     <string name="search_recently_added">Recently added</string>