Addition of Dark Theme and Compatibility with Android 10 Dark Mode

This commit adds support for Android Night Mode and adds in a dark theme for the UI.
This commit is contained in:
◱ PixelyIon 2019-12-11 02:21:02 +05:30 committed by ◱ PixelyIon
parent 4ab9af04ff
commit 8d1545aabf
25 changed files with 144 additions and 67 deletions

View File

@ -54,10 +54,11 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.preference:preference:1.1.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.google.android.material:material:1.2.0-alpha02'
implementation 'me.xdrop:fuzzywuzzy:1.2.0'
implementation "androidx.core:core-ktx:1.1.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.documentfile:documentfile:1.0.1'
}
repositories {
mavenCentral()

View File

@ -12,6 +12,7 @@ import android.view.View
import android.widget.AdapterView
import android.widget.AdapterView.OnItemClickListener
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.widget.SearchView
import androidx.documentfile.provider.DocumentFile
import androidx.preference.PreferenceManager
@ -28,6 +29,7 @@ import java.io.File
import java.io.IOException
import java.util.*
class MainActivity : AppCompatActivity(), View.OnClickListener {
private lateinit var sharedPreferences: SharedPreferences
private var adapter = GameAdapter(this)
@ -67,21 +69,30 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
Log.w("refreshFiles", "Ran into exception while loading: " + e.message)
}
}
adapter.clear()
val entries: List<TitleEntry> = findFile("nro", NroLoader(this), DocumentFile.fromTreeUri(this, Uri.parse(sharedPreferences.getString("search_location", "")))!!, ArrayList())
if (entries.isNotEmpty()) {
adapter.addHeader(getString(R.string.nro))
for (entry in entries)
adapter.addItem(GameItem(entry))
} else {
adapter.addHeader(getString(R.string.no_rom))
}
try {
adapter.save(File(applicationInfo.dataDir + "/roms.bin"))
} catch (e: IOException) {
Log.w("refreshFiles", "Ran into exception while saving: " + e.message)
adapter.clear()
val entries: List<TitleEntry> = findFile("nro", NroLoader(this), DocumentFile.fromTreeUri(this, Uri.parse(sharedPreferences.getString("search_location", "")))!!, ArrayList())
if (entries.isNotEmpty()) {
adapter.addHeader(getString(R.string.nro))
for (entry in entries)
adapter.addItem(GameItem(entry))
} else {
adapter.addHeader(getString(R.string.no_rom))
}
try {
adapter.save(File(applicationInfo.dataDir + "/roms.bin"))
} catch (e: IOException) {
Log.w("refreshFiles", "Ran into exception while saving: " + e.message)
}
sharedPreferences.edit().putBoolean("refresh_required", false).apply()
} catch (e: IllegalArgumentException) {
sharedPreferences.edit().remove("search_location").apply()
val intent = intent
finish()
startActivity(intent)
} catch (e: Exception) {
notifyUser(e.message!!)
}
sharedPreferences.edit().putBoolean("refresh_required", false).apply()
}
override fun onCreate(savedInstanceState: Bundle?) {
@ -89,6 +100,12 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
setContentView(R.layout.main_activity)
PreferenceManager.setDefaultValues(this, R.xml.preferences, false)
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
AppCompatDelegate.setDefaultNightMode(when ((sharedPreferences.getString("app_theme", "2")?.toInt())) {
0 -> AppCompatDelegate.MODE_NIGHT_NO
1 -> AppCompatDelegate.MODE_NIGHT_YES
2 -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
else -> AppCompatDelegate.MODE_NIGHT_UNSPECIFIED
})
setSupportActionBar(toolbar)
open_fab.setOnClickListener(this)
log_fab.setOnClickListener(this)

View File

@ -18,7 +18,7 @@ enum class TitleFormat {
}
internal class TitleEntry(var name: String, var author: String, var romType: TitleFormat, var valid: Boolean, @Transient var uri: Uri, @Transient var icon: Bitmap) : Serializable {
constructor(context: Context, author: String, romType: TitleFormat, valid: Boolean, uri: Uri) : this("", author, romType, valid, uri, context.resources.getDrawable(R.drawable.ic_missing_icon, context.theme).toBitmap(256, 256)) {
constructor(context: Context, author: String, romType: TitleFormat, valid: Boolean, uri: Uri) : this("", author, romType, valid, uri, context.resources.getDrawable(R.drawable.ic_missing, context.theme).toBitmap(256, 256)) {
context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
val nameIndex: Int = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
cursor.moveToFirst()

View File

@ -0,0 +1,24 @@
package emu.skyline.utility
import android.content.Context
import android.util.AttributeSet
import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.ListPreference
class ThemePreference : ListPreference {
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?) : super(context)
override fun callChangeListener(newValue: Any?): Boolean {
AppCompatDelegate.setDefaultNightMode(when((newValue as String).toInt()) {
0 -> AppCompatDelegate.MODE_NIGHT_NO
1 -> AppCompatDelegate.MODE_NIGHT_YES
2 -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
else -> AppCompatDelegate.MODE_NIGHT_UNSPECIFIED
})
return super.callChangeListener(newValue)
}
}

View File

@ -1,10 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:alpha="0.85"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFF"
android:fillColor="?attr/colorOnPrimary"
android:pathData="M5,13h14v-2L5,11v2zM3,17h14v-2L3,15v2zM7,7v2h14L21,7L7,7z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFF"
android:fillColor="?attr/colorOnSecondary"
android:pathData="M7,5h10v2h2L19,3c0,-1.1 -0.9,-1.99 -2,-1.99L7,1c-1.1,0 -2,0.9 -2,2v4h2L7,5zM15.41,16.59L20,12l-4.59,-4.59L14,8.83 17.17,12 14,15.17l1.41,1.42zM10,15.17L6.83,12 10,8.83 8.59,7.41 4,12l4.59,4.59L10,15.17zM17,19L7,19v-2L5,17v4c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2v-4h-2v2z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorSecondaryVariant"
android:pathData="M15.73,3L8.27,3L3,8.27v7.46L8.27,21h7.46L21,15.73L21,8.27L15.73,3zM12,17.3c-0.72,0 -1.3,-0.58 -1.3,-1.3 0,-0.72 0.58,-1.3 1.3,-1.3 0.72,0 1.3,0.58 1.3,1.3 0,0.72 -0.58,1.3 -1.3,1.3zM13,13h-2L11,7h2v6z" />
</vector>

View File

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:alpha="0.6"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13L7,13v-2h10v2z" />
</vector>

View File

@ -1,5 +1,9 @@
<vector android:height="24dp"
android:tint="#FFFFFF" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M19,4L5,4c-1.11,0 -2,0.9 -2,2v12c0,1.1 0.89,2 2,2h4v-2L5,18L5,8h14v10h-4v2h4c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.89,-2 -2,-2zM12,10l-4,4h3v6h2v-6h3l-4,-4z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorOnSecondary"
android:pathData="M19,4L5,4c-1.11,0 -2,0.9 -2,2v12c0,1.1 0.89,2 2,2h4v-2L5,18L5,8h14v10h-4v2h4c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.89,-2 -2,-2zM12,10l-4,4h3v6h2v-6h3l-4,-4z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFF"
android:fillColor="?attr/colorOnPrimary"
android:pathData="M12,4L12,1L8,5l4,4L12,6c3.31,0 6,2.69 6,6 0,1.01 -0.25,1.97 -0.7,2.8l1.46,1.46C19.54,15.03 20,13.57 20,12c0,-4.42 -3.58,-8 -8,-8zM12,18c-3.31,0 -6,-2.69 -6,-6 0,-1.01 0.25,-1.97 0.7,-2.8L5.24,7.74C4.46,8.97 4,10.43 4,12c0,4.42 3.58,8 8,8v3l4,-4 -4,-4v3z" />
</vector>

View File

@ -1,11 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:alpha="0.85"
android:tint="#FFFFFF"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:fillColor="?attr/colorOnPrimary"
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z" />
</vector>

View File

@ -1,10 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:alpha="0.85"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFF"
android:fillColor="?attr/colorOnPrimary"
android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z" />
</vector>

View File

@ -1,11 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:alpha="0.85"
android:tint="#FFFFFF"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:fillColor="?attr/colorOnPrimary"
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z" />
</vector>

View File

@ -13,7 +13,7 @@
android:layout_alignParentTop="false"
android:layout_centerVertical="true"
android:contentDescription="@string/icon"
android:src="@drawable/ic_missing_icon" />
android:src="@drawable/ic_missing" />
<TextView
android:id="@+id/text_title"

View File

@ -12,8 +12,8 @@
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:popupTheme="@style/ThemeOverlay.MaterialComponents.Light"
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar"
android:theme="@style/AppTheme.ActionBar"
app:popupTheme="@style/AppTheme.PopupMenu"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

View File

@ -12,8 +12,8 @@
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:popupTheme="@style/ThemeOverlay.MaterialComponents.Light"
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar"
android:theme="@style/AppTheme.ActionBar"
app:popupTheme="@style/AppTheme.PopupMenu"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@ -30,8 +30,7 @@
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:paddingBottom="8dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent">
@ -40,6 +39,7 @@
android:id="@+id/open_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:clickable="true"
android:focusable="true"
@ -49,6 +49,8 @@
android:id="@+id/log_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:clickable="true"
android:focusable="true"
app:srcCompat="@drawable/ic_log" />

View File

@ -13,7 +13,7 @@
android:layout_marginStart="5dp"
android:layout_marginTop="2dp"
android:layout_marginEnd="5dp"
android:textColor="@color/colorPrimary"
android:textColor="?colorSecondary"
android:textSize="13sp" />
</RelativeLayout>

View File

@ -10,7 +10,8 @@
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:theme="@style/AppTheme.ActionBar"
app:popupTheme="@style/AppTheme.PopupMenu"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

View File

@ -4,6 +4,7 @@
<item
android:id="@+id/action_search_main"
android:icon="@drawable/ic_search"
android:iconTint="@color/colorOnPrimary"
android:title="@string/search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="ifRoom|withText" />

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#FFFF0000</color>
<color name="colorPrimaryDark">#BFFF0000</color>
<color name="colorOnPrimary">#D7000000</color>
<color name="colorSecondary">#FFFF0000</color>
<color name="colorSecondaryDark">#BFFF0000</color>
<color name="colorOnSecondary">#DF000000</color>
</resources>

View File

@ -12,4 +12,14 @@
<item>2</item>
<item>3</item>
</string-array>
<string-array name="app_theme">
<item>Light</item>
<item>Dark</item>
<item>Use System Default</item>
</string-array>
<string-array name="app_theme_val">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
</resources>

View File

@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#E60012</color>
<color name="colorPrimaryDark">#AB0000</color>
<color name="colorAccent">#E60012</color>
</resources>
<color name="colorPrimary">#FFFF0000</color>
<color name="colorPrimaryDark">#BFFF0000</color>
<color name="colorOnPrimary">#DFFFFFFF</color>
<color name="colorSecondary">#FFFF0000</color>
<color name="colorSecondaryDark">#BFFF0000</color>
<color name="colorOnSecondary">#DFFFFFFF</color>
</resources>

View File

@ -21,8 +21,8 @@
<string name="share_error">An error has occurred while sharing</string>
<string name="cleared">The logs have been cleared</string>
<!-- Settings -->
<string name="emulator">Emulator</string>
<string name="search_location">Search Location</string>
<string name="logging">Logging</string>
<string name="log_level">Log Level</string>
<string name="log_compact">Compact Logs</string>
<string name="log_compact_desc_on">Logs will be displayed in a compact form factor</string>
@ -31,4 +31,5 @@
<string name="use_docked">Use Docked Mode</string>
<string name="handheld_enabled">The system will emulate being in handheld mode</string>
<string name="docked_enabled">The system will emulate being in docked mode</string>
<string name="theme">Theme</string>
</resources>

View File

@ -1,10 +1,18 @@
<resources>
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Switch Red Theme -->
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="colorPrimaryVariant">@color/colorPrimaryDark</item>
<item name="colorOnPrimary">@color/colorOnPrimary</item>
<item name="colorSecondary">@color/colorSecondary</item>
<item name="colorSecondaryVariant">@color/colorSecondaryDark</item>
<item name="colorOnSecondary">@color/colorOnSecondary</item>
</style>
<style name="AppTheme.ActionBar" parent="ThemeOverlay.MaterialComponents.ActionBar">
<item name="android:background">@color/colorPrimary</item>
<item name="android:textColorPrimary">@color/colorOnPrimary</item>
</style>
<style name="AppTheme.PopupMenu" parent="Widget.AppCompat.PopupMenu">
<item name="android:background">@color/colorPrimary</item>
<item name="android:textColorPrimary">@color/colorOnPrimary</item>
</style>
</resources>

View File

@ -17,16 +17,19 @@
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
android:key="category_search"
android:title="@string/search">
android:key="category_emulator"
android:title="@string/emulator">
<emu.skyline.utility.FolderPreference
app:key="search_location"
app:title="@string/search_location"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory>
<PreferenceCategory
android:key="category_log"
android:title="@string/logging">
<emu.skyline.utility.ThemePreference
android:defaultValue="2"
android:entries="@array/app_theme"
android:entryValues="@array/app_theme_val"
app:key="app_theme"
app:title="@string/theme"
app:useSimpleSummaryProvider="true" />
<ListPreference
android:defaultValue="2"
android:entries="@array/log_level"