Update android studio. Add compose settings screen.
Some checks are pending
continuous-integration/drone/push Build is pending
Some checks are pending
continuous-integration/drone/push Build is pending
This commit is contained in:
@@ -30,7 +30,7 @@ android {
|
||||
targetSdkVersion 33
|
||||
versionCode versionProperties["versionCode"].toInteger()
|
||||
versionName "1.1.0Beta1"
|
||||
resConfigs("de", "en")
|
||||
resConfigs 'de', 'en'
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
vectorDrawables {
|
||||
|
||||
@@ -7,17 +7,23 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import me.zobrist.tichucounter.domain.Language
|
||||
import me.zobrist.tichucounter.domain.SettingsAdapter
|
||||
import me.zobrist.tichucounter.domain.Theme
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
@AndroidEntryPoint
|
||||
abstract class BaseActivity : AppCompatActivity(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
@Inject
|
||||
lateinit var settingsAdapter: SettingsAdapter
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
keepScreenOn(sharedPreferences.getBoolean("screen_on", false))
|
||||
updateTheme(sharedPreferences.getString("theme", null))
|
||||
keepScreenOn(settingsAdapter.keepScreenOn)
|
||||
updateTheme(settingsAdapter.theme)
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.registerOnSharedPreferenceChangeListener(this)
|
||||
@@ -37,20 +43,19 @@ abstract class BaseActivity : AppCompatActivity(),
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) {
|
||||
when (key) {
|
||||
"language" -> setLanguage(sharedPreferences.getString(key, null))
|
||||
"screen_on" -> keepScreenOn(sharedPreferences.getBoolean(key, false))
|
||||
"theme" -> updateTheme(sharedPreferences.getString(key, null))
|
||||
settingsAdapter.language::class.simpleName -> setLanguage(settingsAdapter.language)
|
||||
settingsAdapter.keepScreenOn::class.simpleName -> keepScreenOn(settingsAdapter.keepScreenOn)
|
||||
settingsAdapter.theme::class.simpleName -> updateTheme(settingsAdapter.theme)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun updateTheme(theme: String?) {
|
||||
private fun updateTheme(theme: Theme) {
|
||||
|
||||
val themeValue = when (theme) {
|
||||
"light" -> AppCompatDelegate.MODE_NIGHT_NO
|
||||
"dark" -> AppCompatDelegate.MODE_NIGHT_YES
|
||||
"default" -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
Theme.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO
|
||||
Theme.DARK -> AppCompatDelegate.MODE_NIGHT_YES
|
||||
Theme.DEFAULT -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
}
|
||||
|
||||
if (themeValue != AppCompatDelegate.getDefaultNightMode()) {
|
||||
@@ -67,7 +72,13 @@ abstract class BaseActivity : AppCompatActivity(),
|
||||
}
|
||||
}
|
||||
|
||||
private fun setLanguage(locale: String?) {
|
||||
private fun setLanguage(language: Language) {
|
||||
|
||||
val locale = when (language) {
|
||||
Language.ENGLISH -> "en"
|
||||
Language.GERMAN -> "de"
|
||||
else -> null
|
||||
}
|
||||
|
||||
val currentLocale = AppCompatDelegate.getApplicationLocales()[0].toString()
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ import me.zobrist.tichucounter.ui.MainViewModel
|
||||
import me.zobrist.tichucounter.ui.counter.*
|
||||
import me.zobrist.tichucounter.ui.history.HistoryList
|
||||
import me.zobrist.tichucounter.ui.history.HistoryViewModel
|
||||
import me.zobrist.tichucounter.ui.settings.SettingsView
|
||||
import me.zobrist.tichucounter.ui.settings.SettingsViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@@ -41,6 +43,7 @@ class MainActivity : BaseActivity() {
|
||||
|
||||
private val counterViewModel: CounterViewModel by viewModels()
|
||||
private val historyViewModel: HistoryViewModel by viewModels()
|
||||
private val settingsViewModel: SettingsViewModel by viewModels()
|
||||
private val mainViewModel: MainViewModel by viewModels()
|
||||
|
||||
|
||||
@@ -79,9 +82,7 @@ class MainActivity : BaseActivity() {
|
||||
|
||||
}
|
||||
composable("settings") {
|
||||
Column() {
|
||||
Text("Settings")
|
||||
}
|
||||
SettingsView(settingsViewModel)
|
||||
mainViewModel.setActions(emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package me.zobrist.tichucounter.domain
|
||||
|
||||
import android.content.Context
|
||||
import androidx.preference.PreferenceManager
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
|
||||
enum class Theme { DEFAULT, DARK, LIGHT }
|
||||
enum class Language { DEFAULT, GERMAN, ENGLISH }
|
||||
|
||||
|
||||
class SettingsAdapter @Inject constructor(@ApplicationContext private val context: Context) {
|
||||
|
||||
private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
|
||||
val language: Language
|
||||
get() {
|
||||
return Language.values()[sharedPreferences.getInt(Language::class.simpleName, 0)]
|
||||
}
|
||||
|
||||
val theme: Theme
|
||||
get() {
|
||||
return Theme.values()[sharedPreferences.getInt(Theme::class.simpleName, 0)]
|
||||
}
|
||||
|
||||
val keepScreenOn: Boolean
|
||||
get() {
|
||||
return sharedPreferences.getBoolean("keep_screen_on", false)
|
||||
}
|
||||
|
||||
|
||||
fun setLanguage(language: Language) {
|
||||
val editor = sharedPreferences.edit()
|
||||
editor.putInt(Language::class.simpleName, language.ordinal)
|
||||
editor.commit()
|
||||
}
|
||||
|
||||
fun setTheme(theme: Theme) {
|
||||
val editor = sharedPreferences.edit()
|
||||
editor.putInt(Theme::class.simpleName, theme.ordinal)
|
||||
editor.commit()
|
||||
}
|
||||
|
||||
fun setKeepScreenOn(setting: Boolean) {
|
||||
val editor = sharedPreferences.edit()
|
||||
editor.putBoolean("keep_screen_on", setting)
|
||||
editor.commit()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package me.zobrist.tichucounter.ui.settings
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Check
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import me.zobrist.tichucounter.R
|
||||
import me.zobrist.tichucounter.domain.Language
|
||||
import me.zobrist.tichucounter.domain.Theme
|
||||
|
||||
|
||||
val languageMap = mapOf(
|
||||
Language.DEFAULT to R.string.android_default_text,
|
||||
Language.ENGLISH to R.string.english,
|
||||
Language.GERMAN to R.string.german
|
||||
)
|
||||
|
||||
val themeMap = mapOf(
|
||||
Theme.DEFAULT to R.string.android_default_text,
|
||||
Theme.DARK to R.string.dark,
|
||||
Theme.LIGHT to R.string.light
|
||||
)
|
||||
|
||||
|
||||
@Composable
|
||||
fun SettingsView(viewModel: SettingsViewModel) {
|
||||
SettingsView(
|
||||
viewModel.screenOn,
|
||||
viewModel.language,
|
||||
viewModel.theme,
|
||||
{ viewModel.updateScreenOn(it) },
|
||||
{ viewModel.updateLanguage(it) },
|
||||
{ viewModel.updateTheme(it) })
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SettingsView(
|
||||
valueScreenOn: Boolean = true,
|
||||
valueLanguage: Language = Language.ENGLISH,
|
||||
valueTheme: Theme = Theme.DARK,
|
||||
updateScreenOn: (Boolean) -> Unit = {},
|
||||
updateLanguage: (Language) -> Unit = {},
|
||||
updateTheme: (Theme) -> Unit = {}
|
||||
) {
|
||||
Column() {
|
||||
BooleanSetting(
|
||||
stringResource(R.string.keep_screen_on),
|
||||
valueScreenOn
|
||||
) { updateScreenOn(it) }
|
||||
|
||||
StringSetting(
|
||||
stringResource(R.string.choose_language_text),
|
||||
languageMap,
|
||||
valueLanguage,
|
||||
) { updateLanguage(it) }
|
||||
|
||||
StringSetting(
|
||||
stringResource(R.string.choose_theme_text),
|
||||
themeMap,
|
||||
valueTheme,
|
||||
) { updateTheme(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BooleanSetting(name: String, value: Boolean, updateValue: (Boolean) -> Unit) {
|
||||
Row {
|
||||
Column() {
|
||||
Text(text = name)
|
||||
}
|
||||
Column() {
|
||||
Checkbox(checked = value, onCheckedChange = { updateValue(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun <T> StringSetting(name: String, map: Map<T, Int>, selected: T, onSelected: (T) -> Unit) {
|
||||
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
|
||||
Row() {
|
||||
TextField(
|
||||
value = stringResource(map[selected]!!),
|
||||
onValueChange = { },
|
||||
singleLine = true,
|
||||
label = { Text(name) },
|
||||
readOnly = true,
|
||||
modifier = Modifier
|
||||
.onFocusChanged {
|
||||
if (it.isFocused) {
|
||||
expanded = true
|
||||
}
|
||||
}
|
||||
)
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false }
|
||||
) {
|
||||
map.forEach {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
onSelected(it.key)
|
||||
expanded = false
|
||||
},
|
||||
text = { Text(stringResource(it.value)) },
|
||||
trailingIcon = {
|
||||
if (it.key == selected) {
|
||||
Icon(Icons.Outlined.Check, contentDescription = null)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package me.zobrist.tichucounter.ui.settings
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import me.zobrist.tichucounter.domain.Language
|
||||
import me.zobrist.tichucounter.domain.SettingsAdapter
|
||||
import me.zobrist.tichucounter.domain.Theme
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class SettingsViewModel @Inject constructor(private val settings: SettingsAdapter) : ViewModel() {
|
||||
|
||||
|
||||
var language by mutableStateOf(settings.language)
|
||||
private set
|
||||
|
||||
var theme by mutableStateOf(settings.theme)
|
||||
private set
|
||||
|
||||
var screenOn by mutableStateOf(false)
|
||||
private set
|
||||
|
||||
fun updateLanguage(language: Language) {
|
||||
settings.setLanguage(language)
|
||||
this.language = settings.language
|
||||
}
|
||||
|
||||
fun updateTheme(theme: Theme) {
|
||||
settings.setTheme(theme)
|
||||
this.theme = settings.theme
|
||||
}
|
||||
|
||||
fun updateScreenOn(value: Boolean) {
|
||||
settings.setKeepScreenOn(value)
|
||||
screenOn = settings.keepScreenOn
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 KiB |
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:showIn="navigation_view">
|
||||
|
||||
<group android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/nav_counter"
|
||||
android:icon="@drawable/ic_menu_camera"
|
||||
android:title="@string/menu_counter" />
|
||||
<item
|
||||
android:id="@+id/nav_history"
|
||||
android:icon="@drawable/ic_menu_gallery"
|
||||
android:title="@string/menu_history" />
|
||||
<item
|
||||
android:id="@+id/nav_settings"
|
||||
android:icon="@drawable/ic_menu_slideshow"
|
||||
android:title="@string/menu_settings" />
|
||||
</group>
|
||||
</menu>
|
||||
@@ -1,18 +0,0 @@
|
||||
<menu 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"
|
||||
tools:context="me.zobrist.tichucounter.MainActivity">
|
||||
<item
|
||||
android:id="@+id/action_undo"
|
||||
android:icon="@drawable/ic_baseline_undo_24"
|
||||
android:orderInCategory="5"
|
||||
android:title="@string/undo"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/action_new"
|
||||
android:checkable="false"
|
||||
android:icon="@drawable/ic_baseline_add_24"
|
||||
android:orderInCategory="10"
|
||||
android:title="@string/clear"
|
||||
app:showAsAction="ifRoom" />
|
||||
</menu>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?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"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/mobile_navigation"
|
||||
app:startDestination="@+id/nav_counter">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_counter"
|
||||
android:name="me.zobrist.tichucounter.ui.counter.CounterFragment"
|
||||
android:label="@string/menu_counter"
|
||||
tools:layout="@layout/fragment_counter" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_history"
|
||||
android:name="me.zobrist.tichucounter.ui.history.HistoryFragment"
|
||||
android:label="@string/menu_history"
|
||||
tools:layout="@layout/fragment_slideshow" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_settings"
|
||||
android:name="me.zobrist.tichucounter.ui.settings.SettingsFragment"
|
||||
android:label="@string/menu_settings" />
|
||||
</navigation>
|
||||
@@ -1,25 +0,0 @@
|
||||
<resources>
|
||||
<!-- Theme Preference -->
|
||||
<string-array name="theme_entries">
|
||||
<item>@string/dark</item>
|
||||
<item>@string/light</item>
|
||||
<item>@string/android_default_text</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="theme_values">
|
||||
<item>dark</item>
|
||||
<item>light</item>
|
||||
<item>default</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Language Preference -->
|
||||
<string-array name="language_entries">
|
||||
<item>@string/english</item>
|
||||
<item>@string/german</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="language_values">
|
||||
<item>en</item>
|
||||
<item>de</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
@@ -9,7 +9,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.3.1'
|
||||
classpath 'com.android.tools.build:gradle:7.4.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
@@ -16,6 +16,6 @@ org.gradle.jvmargs=-Xmx2048m
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
android.enableJetifier=false
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
|
||||
|
||||
Reference in New Issue
Block a user