diff --git a/.idea/androidTestResultsUserPreferences.xml b/.idea/androidTestResultsUserPreferences.xml
new file mode 100644
index 0000000..1ff8cba
--- /dev/null
+++ b/.idea/androidTestResultsUserPreferences.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index f3c1f83..01d3b93 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,6 +1,7 @@
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
+
}
android {
@@ -43,6 +44,9 @@ android {
androidResources {
generateLocaleConfig = true
}
+ buildFeatures{
+ viewBinding = true
+ }
}
dependencies {
@@ -68,6 +72,8 @@ dependencies {
implementation(libs.androidx.annotation)
implementation(libs.androidx.lifecycle.livedata.ktx)
implementation(libs.androidx.lifecycle.viewmodel.ktx)
+ implementation(libs.androidx.datastore.rxjava3)
+ implementation(libs.androidx.datastore.preferences)
testImplementation(libs.junit)
diff --git a/app/src/androidTest/java/uk/kagurach/android101/TestColorHelper.kt b/app/src/androidTest/java/uk/kagurach/android101/TestColorHelper.kt
new file mode 100644
index 0000000..817d96a
--- /dev/null
+++ b/app/src/androidTest/java/uk/kagurach/android101/TestColorHelper.kt
@@ -0,0 +1,31 @@
+package uk.kagurach.android101
+
+import org.junit.Assert
+import org.junit.Test
+import uk.kagurach.android101.helper.ColorHelper
+import org.junit.runner.RunWith
+
+
+class TestColorHelper {
+ val colorHelper = ColorHelper()
+
+ @Test
+ fun Test_toColorInt(){
+ Assert.assertEquals(0,colorHelper.toColorInt(0, 0, 0))
+ Assert.assertEquals(0xfffffe,colorHelper.toColorInt(255, 0xff, 254))
+ }
+
+ @Test(expected = Exception::class)
+ fun Test_error(){
+ val wtf1 = colorHelper.toColorInt(-1,256,1)
+ }
+ @Test
+ fun Test_toString(){
+ Assert.assertEquals("$000000",colorHelper.toString(0,"$"))
+ Assert.assertEquals("#ffffff",colorHelper.toString(0xffffff))
+ Assert.assertEquals("#ABCD12",colorHelper.toString(0xabcd12, upperCase = true))
+
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 08b5324..c5955c9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,7 +2,6 @@
-
+
-
+
diff --git a/app/src/main/java/uk/kagurach/android101/KaBaseActivity.kt b/app/src/main/java/uk/kagurach/android101/KaBaseActivity.kt
new file mode 100644
index 0000000..aa21f22
--- /dev/null
+++ b/app/src/main/java/uk/kagurach/android101/KaBaseActivity.kt
@@ -0,0 +1,14 @@
+package uk.kagurach.android101
+
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import kotlinx.coroutines.runBlocking
+
+
+open class KaBaseActivity : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val storage = SettingStorage(this)
+ this.setTheme(runBlocking { storage.getDefaultTheme() })
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/uk/kagurach/android101/MainActivity.java b/app/src/main/java/uk/kagurach/android101/MainActivity.java
index 15707d5..96724b6 100644
--- a/app/src/main/java/uk/kagurach/android101/MainActivity.java
+++ b/app/src/main/java/uk/kagurach/android101/MainActivity.java
@@ -27,7 +27,7 @@ import java.util.Arrays;
import uk.kagurach.android101.helper.PageHelper;
-public class MainActivity extends AppCompatActivity {
+public class MainActivity extends KaBaseActivity {
PageHelper pageHelper;
@Override
@@ -62,7 +62,7 @@ public class MainActivity extends AppCompatActivity {
101);
}
textViewAppendString(tv, "Check Finished");
- textViewAppendString(tv, "提示:常桉有惊喜");
+ textViewAppendString(tv, "提示:常按有惊喜");
}
textViewAppendString(tv, "*************************\nfinished");
@@ -73,6 +73,9 @@ public class MainActivity extends AppCompatActivity {
button.setEnabled(true);
button.setOnClickListener(pageHelper.pageButtonHandler);
button.setOnLongClickListener(new LongClickHandler(this));
+
+ Button SettingPageButton = findViewById(R.id.P1OpenAppSettingsLayout);
+ SettingPageButton.setOnClickListener(new SettingPageHandler());
}
private void textViewAppendString(@NonNull TextView tv, String s) {
@@ -121,4 +124,15 @@ public class MainActivity extends AppCompatActivity {
return false;
}
}
+
+ private final class SettingPageHandler implements View.OnClickListener {
+
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(v.getContext(),SettingPage.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);
+ finish();
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/uk/kagurach/android101/MainActivity2.java b/app/src/main/java/uk/kagurach/android101/MainActivity2.java
index d5b4b03..ca234f9 100644
--- a/app/src/main/java/uk/kagurach/android101/MainActivity2.java
+++ b/app/src/main/java/uk/kagurach/android101/MainActivity2.java
@@ -21,10 +21,11 @@ import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
+import uk.kagurach.android101.helper.ColorHelper;
import uk.kagurach.android101.helper.PageHelper;
import uk.kagurach.android101.helper.ToastHelper;
-public class MainActivity2 extends AppCompatActivity {
+public class MainActivity2 extends KaBaseActivity {
PageHelper pageHelper;
@@ -159,9 +160,8 @@ public class MainActivity2 extends AppCompatActivity {
private void updateCurrentSettingShower(){
TextView tv = findViewById(R.id.P2SettingResult);
- String sb = "Color = #" +
- String.format("%6s",Integer.toString(_text_color&0xffffff, 16))
- .replace(" ","0") +
+ String sb = "Color = " +
+ new ColorHelper().toString(_text_color,"#",false) +
"; TextSize = " +
_text_size +
"." +
diff --git a/app/src/main/java/uk/kagurach/android101/Page3.java b/app/src/main/java/uk/kagurach/android101/Page3.java
index bbf10df..de9fac9 100644
--- a/app/src/main/java/uk/kagurach/android101/Page3.java
+++ b/app/src/main/java/uk/kagurach/android101/Page3.java
@@ -16,7 +16,7 @@ import androidx.core.view.WindowInsetsCompat;
import uk.kagurach.android101.helper.PageHelper;
-public class Page3 extends AppCompatActivity {
+public class Page3 extends KaBaseActivity {
PageHelper pageHelper;
diff --git a/app/src/main/java/uk/kagurach/android101/Page4.java b/app/src/main/java/uk/kagurach/android101/Page4.java
index 78c5152..c890ec5 100644
--- a/app/src/main/java/uk/kagurach/android101/Page4.java
+++ b/app/src/main/java/uk/kagurach/android101/Page4.java
@@ -22,7 +22,7 @@ import androidx.core.view.WindowInsetsCompat;
import uk.kagurach.android101.helper.PageHelper;
import uk.kagurach.android101.misc.vibrationBroadcastReceiver.vibrationBroadcastReceiver;
-public class Page4 extends AppCompatActivity {
+public class Page4 extends KaBaseActivity {
PageHelper pageHelper;
ActivityResultLauncher mLauncher;
diff --git a/app/src/main/java/uk/kagurach/android101/Page5.java b/app/src/main/java/uk/kagurach/android101/Page5.java
index dfa70a7..0c20a9f 100644
--- a/app/src/main/java/uk/kagurach/android101/Page5.java
+++ b/app/src/main/java/uk/kagurach/android101/Page5.java
@@ -25,7 +25,7 @@ import uk.kagurach.android101.helper.PageHelper;
import uk.kagurach.android101.helper.ToastHelper;
import uk.kagurach.android101.helper.AutoCompleHelper.AnimalTypeAutoCompleteHelper;
-public class Page5 extends AppCompatActivity {
+public class Page5 extends KaBaseActivity {
AnimalTypeAutoCompleteHelper completeHelper = null;
final AnimalDatabaseHelper dbHelper = new AnimalDatabaseHelper(this);
diff --git a/app/src/main/java/uk/kagurach/android101/SettingPage.kt b/app/src/main/java/uk/kagurach/android101/SettingPage.kt
new file mode 100644
index 0000000..2e7a6c8
--- /dev/null
+++ b/app/src/main/java/uk/kagurach/android101/SettingPage.kt
@@ -0,0 +1,88 @@
+package uk.kagurach.android101
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import android.widget.ImageButton
+import androidx.activity.enableEdgeToEdge
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.intPreferencesKey
+import androidx.datastore.preferences.preferencesDataStore
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.runBlocking
+import uk.kagurach.android101.databinding.ActivitySettingPageBinding
+
+import uk.kagurach.android101.helper.ColorHelper
+
+val Context.datastore by preferencesDataStore(name = "settings")
+val DefaultColor = intPreferencesKey("default_color")
+
+class SettingPage : KaBaseActivity() {
+ lateinit var binding: ActivitySettingPageBinding
+ lateinit var settingStorage: SettingStorage
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_setting_page)
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
+ val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
+ insets
+ }
+ binding = ActivitySettingPageBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ settingStorage = SettingStorage(this)
+
+ binding.ThemeRed.setOnClickListener(SetColorHandler())
+ binding.ThemeBlue.setOnClickListener(SetColorHandler())
+ binding.ThemeCyan.setOnClickListener(SetColorHandler())
+ binding.ThemePink.setOnClickListener(SetColorHandler())
+ binding.ThemeGreen.setOnClickListener(SetColorHandler())
+
+ binding.SettingPageSubmit.setOnClickListener(FinishButtonHandler())
+ }
+
+
+ inner class SetColorHandler: View.OnClickListener {
+ override fun onClick(v: View?) {
+ if (v == null){
+ return
+ }
+
+ val colorTheme = when(v.id){
+ R.id.ThemeBlue -> R.style.Theme_Blue
+ R.id.ThemeGreen -> R.style.Theme_Green
+ R.id.ThemeRed -> R.style.Theme_Red
+ R.id.ThemeCyan -> R.style.Theme_Cyan
+ R.id.ThemePink -> R.style.Theme_Pink
+ else -> {throw RuntimeException("Impossible branch met!")}
+ }
+
+ runBlocking {
+ settingStorage.setDefaultTheme(colorTheme)
+ }
+
+ val intent = Intent(v.context,this@SettingPage::class.java)
+ startActivity(intent)
+ finish()
+ }
+ }
+
+ inner class FinishButtonHandler: View.OnClickListener{
+ override fun onClick(v: View?) {
+ val intent = Intent(v!!.context,MainActivity::class.java)
+ startActivity(intent)
+ finish()
+ }
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/uk/kagurach/android101/SettingStorage.kt b/app/src/main/java/uk/kagurach/android101/SettingStorage.kt
new file mode 100644
index 0000000..0ed7eb4
--- /dev/null
+++ b/app/src/main/java/uk/kagurach/android101/SettingStorage.kt
@@ -0,0 +1,28 @@
+package uk.kagurach.android101
+
+import android.content.Context
+import androidx.datastore.preferences.core.edit
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
+
+class SettingStorage(val context: Context) {
+
+ suspend fun getDefaultTheme(): Int {
+ return getDefaultColorFlow.first()
+ }
+ suspend fun setDefaultTheme(newValue: Int) {
+ context.datastore.edit {
+ preferences ->
+ preferences[DefaultColor] = newValue
+ }
+ }
+
+
+ private val getDefaultColorFlow: Flow =
+ context.datastore.data
+ .map {
+ preferences ->
+ preferences[DefaultColor] ?: R.id.ThemeBlue
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/uk/kagurach/android101/helper/ColorHelper.kt b/app/src/main/java/uk/kagurach/android101/helper/ColorHelper.kt
new file mode 100644
index 0000000..2be9a97
--- /dev/null
+++ b/app/src/main/java/uk/kagurach/android101/helper/ColorHelper.kt
@@ -0,0 +1,23 @@
+package uk.kagurach.android101.helper
+
+import android.graphics.Color
+import androidx.compose.ui.util.fastJoinToString
+
+class ColorHelper {
+ fun toColorInt(r: Int, g: Int, b: Int): Int {
+ if (r !in 0..255 || g !in 0..255 || b !in 0..255) {
+ throw Exception("RGB not in range")
+ }
+ return Color.rgb(r, g, b).and(0xffffff) // Preserve only low 48 bit
+ }
+
+ @OptIn(ExperimentalStdlibApi::class)
+ fun toString(colorInt: Int, start: String = "#", upperCase: Boolean = false): String {
+ val colorInt = colorInt.and(0xffffff) // Keep only low six digit
+ val colorString = colorInt.toHexString(
+ if (upperCase) { HexFormat.UpperCase }
+ else{ HexFormat.Default }
+ ).drop(2)
+ return "$start$colorString"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/uk/kagurach/android101/misc/Kaculate.kt b/app/src/main/java/uk/kagurach/android101/misc/Kaculate.kt
index dac3337..85cd971 100644
--- a/app/src/main/java/uk/kagurach/android101/misc/Kaculate.kt
+++ b/app/src/main/java/uk/kagurach/android101/misc/Kaculate.kt
@@ -9,15 +9,15 @@ fun Kaculate(src: String, ctx: Context): String {
return src
}
- val OpList = charArrayOf('+', '-', 'x', '/', '^')
+ val opList = charArrayOf('+', '-', 'x', '/', '^')
var numStack = floatArrayOf()
var opStack = charArrayOf()
var _curnum = ""
// Fix for expression starts with operator
- val src = if (src[0] in OpList){
- "0" + src
+ val src = if (src[0] in opList){
+ "0$src"
}else{
src
}
@@ -25,7 +25,7 @@ fun Kaculate(src: String, ctx: Context): String {
for (i in src.indices) {
if (src[i] in '0'..'9' || src[i] == '.') {
_curnum += src[i]
- } else if (src[i] in OpList) {
+ } else if (src[i] in opList) {
try {
numStack += _curnum.toFloat()
_curnum = ""
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index f925424..c585eab 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -4,25 +4,51 @@
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".MainActivity">
+ tools:context=".MainActivity"
+ tools:viewBindingIgnore="true">
+ android:orientation="vertical"
+ android:layout_marginHorizontal="15dp"
+ android:layout_marginVertical="10dp"
+ >
-
+ android:layout_height="wrap_content"
+ android:minHeight="500dp"
+ >
+
+
+
+
+
+
+