From 613a68d2095cc88758e15774926cb3b49f34e3d5 Mon Sep 17 00:00:00 2001 From: izzy2lost Date: Sun, 28 Dec 2025 06:50:14 -0500 Subject: [PATCH] added dark/light button and other ui adjustments --- .../java/com/izzy2lost/super3/MainActivity.kt | 87 ++++++++++++++- .../src/main/res/drawable/dark_mode_24px.xml | 10 ++ .../src/main/res/drawable/light_mode_24px.xml | 10 ++ .../app/src/main/res/drawable/search_24px.xml | 10 ++ .../app/src/main/res/layout/activity_main.xml | 103 ++++++++++++++---- android/app/src/main/res/values/strings.xml | 4 + 6 files changed, 201 insertions(+), 23 deletions(-) create mode 100644 android/app/src/main/res/drawable/dark_mode_24px.xml create mode 100644 android/app/src/main/res/drawable/light_mode_24px.xml create mode 100644 android/app/src/main/res/drawable/search_24px.xml diff --git a/android/app/src/main/java/com/izzy2lost/super3/MainActivity.kt b/android/app/src/main/java/com/izzy2lost/super3/MainActivity.kt index d5a9a9c..d11b044 100644 --- a/android/app/src/main/java/com/izzy2lost/super3/MainActivity.kt +++ b/android/app/src/main/java/com/izzy2lost/super3/MainActivity.kt @@ -3,8 +3,10 @@ package com.izzy2lost.super3 import android.content.Intent import android.net.Uri import android.os.Bundle +import android.content.res.Configuration import android.text.method.LinkMovementMethod import android.text.util.Linkify +import android.view.Gravity import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -13,6 +15,8 @@ import android.widget.TextView import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.app.AppCompatDelegate +import androidx.appcompat.content.res.AppCompatResources import androidx.core.view.GravityCompat import androidx.core.widget.addTextChangedListener import androidx.documentfile.provider.DocumentFile @@ -27,6 +31,7 @@ import com.google.android.material.navigation.NavigationView import com.google.android.material.search.SearchBar import com.google.android.material.search.SearchView import java.io.File +import java.util.ArrayDeque import kotlin.math.max import kotlin.math.min import kotlin.concurrent.thread @@ -41,7 +46,9 @@ class MainActivity : AppCompatActivity() { private lateinit var toolbar: MaterialToolbar private lateinit var searchBar: SearchBar private lateinit var searchView: SearchView + private lateinit var btnOpenDrawer: ImageButton private lateinit var btnViewMode: ImageButton + private lateinit var btnThemeToggle: ImageButton private lateinit var btnAbout: MaterialButton private lateinit var gamesFolderText: TextView @@ -119,6 +126,7 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + applyThemeFromPrefs() if (!prefs.getBoolean("setup_complete", false)) { val hasGames = prefs.getString("gamesTreeUri", null) != null val hasData = prefs.getString("userTreeUri", null) != null @@ -138,7 +146,9 @@ class MainActivity : AppCompatActivity() { toolbar = findViewById(R.id.toolbar) searchBar = findViewById(R.id.search_bar) searchView = findViewById(R.id.search_view) + btnOpenDrawer = findViewById(R.id.btn_open_drawer) btnViewMode = findViewById(R.id.btn_view_mode) + btnThemeToggle = findViewById(R.id.btn_theme_toggle) gamesList = findViewById(R.id.games_list) searchResultsList = findViewById(R.id.search_results_list) @@ -170,7 +180,7 @@ class MainActivity : AppCompatActivity() { gamesList.adapter = gamesAdapter searchResultsList.adapter = gamesAdapter - toolbar.setNavigationOnClickListener { + btnOpenDrawer.setOnClickListener { drawerLayout.openDrawer(GravityCompat.START) } @@ -208,6 +218,7 @@ class MainActivity : AppCompatActivity() { } runCatching { searchView.setupWithSearchBar(searchBar) } + styleSearchBarText() searchBar.setOnClickListener { searchView.show() searchView.requestFocusAndShowKeyboard() @@ -242,6 +253,9 @@ class MainActivity : AppCompatActivity() { applyViewMode(viewMode) } + updateThemeToggleIcon() + btnThemeToggle.setOnClickListener { toggleTheme() } + loadPrefs() games = GameXml.parseGamesXmlFromAssets(this) @@ -253,6 +267,77 @@ class MainActivity : AppCompatActivity() { refreshUi() } + private fun applyThemeFromPrefs() { + val mode = + when (prefs.getString("theme_mode", null)) { + "light" -> AppCompatDelegate.MODE_NIGHT_NO + "dark" -> AppCompatDelegate.MODE_NIGHT_YES + else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM + } + if (AppCompatDelegate.getDefaultNightMode() != mode) { + AppCompatDelegate.setDefaultNightMode(mode) + } + } + + private fun toggleTheme() { + val currentlyDark = isNightModeActive() + val mode = + if (currentlyDark) { + prefs.edit().putString("theme_mode", "light").apply() + AppCompatDelegate.MODE_NIGHT_NO + } else { + prefs.edit().putString("theme_mode", "dark").apply() + AppCompatDelegate.MODE_NIGHT_YES + } + AppCompatDelegate.setDefaultNightMode(mode) + recreate() + } + + private fun isNightModeActive(): Boolean { + val mask = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK + return mask == Configuration.UI_MODE_NIGHT_YES + } + + private fun updateThemeToggleIcon() { + if (isNightModeActive()) { + btnThemeToggle.setImageResource(R.drawable.light_mode_24px) + btnThemeToggle.contentDescription = getString(R.string.theme_switch_to_light) + } else { + btnThemeToggle.setImageResource(R.drawable.dark_mode_24px) + btnThemeToggle.contentDescription = getString(R.string.theme_switch_to_dark) + } + } + + private fun styleSearchBarText() { + val textView = findSearchBarTextView() ?: return + textView.gravity = Gravity.CENTER + textView.textAlignment = View.TEXT_ALIGNMENT_CENTER + val icon = AppCompatResources.getDrawable(this, R.drawable.search_24px) ?: return + val tint = + MaterialColors.getColor( + searchBar, + com.google.android.material.R.attr.colorOnSurfaceVariant, + ) + icon.setTint(tint) + textView.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null) + textView.compoundDrawablePadding = (6 * resources.displayMetrics.density).toInt() + } + + private fun findSearchBarTextView(): TextView? { + val queue = ArrayDeque() + queue.add(searchBar) + while (queue.isNotEmpty()) { + val view = queue.removeFirst() + if (view is TextView) return view + if (view is ViewGroup) { + for (i in 0 until view.childCount) { + queue.add(view.getChildAt(i)) + } + } + } + return null + } + private fun showAboutDialog() { val view = layoutInflater.inflate(R.layout.dialog_about, null) val aboutText: TextView = view.findViewById(R.id.about_text) diff --git a/android/app/src/main/res/drawable/dark_mode_24px.xml b/android/app/src/main/res/drawable/dark_mode_24px.xml new file mode 100644 index 0000000..b578c20 --- /dev/null +++ b/android/app/src/main/res/drawable/dark_mode_24px.xml @@ -0,0 +1,10 @@ + + + diff --git a/android/app/src/main/res/drawable/light_mode_24px.xml b/android/app/src/main/res/drawable/light_mode_24px.xml new file mode 100644 index 0000000..612b2db --- /dev/null +++ b/android/app/src/main/res/drawable/light_mode_24px.xml @@ -0,0 +1,10 @@ + + + diff --git a/android/app/src/main/res/drawable/search_24px.xml b/android/app/src/main/res/drawable/search_24px.xml new file mode 100644 index 0000000..390774b --- /dev/null +++ b/android/app/src/main/res/drawable/search_24px.xml @@ -0,0 +1,10 @@ + + + diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml index 727b7ed..572307e 100644 --- a/android/app/src/main/res/layout/activity_main.xml +++ b/android/app/src/main/res/layout/activity_main.xml @@ -13,8 +13,10 @@ android:id="@+id/app_bar" android:layout_width="match_parent" android:layout_height="wrap_content" - android:fitsSystemWindows="true" + android:fitsSystemWindows="false" android:background="?attr/colorPrimary" + android:paddingTop="0dp" + android:paddingBottom="0dp" app:materialThemeOverlay="@style/ThemeOverlay.Material3Expressive.AppBarWithSearch" app:elevation="8dp" app:liftOnScroll="false"> @@ -24,35 +26,92 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/transparent" - app:navigationIcon="@drawable/ic_menu_24" - app:navigationIconTint="?attr/colorOnPrimary"> + android:minHeight="0dp" + android:paddingTop="0dp" + android:paddingBottom="0dp" + android:paddingStart="0dp" + android:paddingEnd="0dp" + app:contentInsetEnd="0dp" + app:contentInsetStart="0dp" + app:contentInsetStartWithNavigation="0dp"> + android:layout_marginEnd="8dp" + android:orientation="vertical"> - + android:layout_marginTop="0dp" + android:layout_marginBottom="0dp"> - + + + + + + + + + + + + + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 32ca279..d9df732 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -29,4 +29,8 @@ Not set Games folder: %1$s Data folder: %1$s + Toggle theme + Switch to light mode + Switch to dark mode + Open menu