Add user-defined button labels with color change on press

- PrefsHelper: PREF_LABEL1, PREF_LABEL2 constants
- SettingsActivity: EditText fields with Done-keyboard action to save labels
- MainActivity: buttons show user label, colorAccent on press, textAllCaps disabled
- activity_main.xml: textAllCaps=false for case-sensitive labels
This commit is contained in:
eddy 2026-07-29 20:25:27 +02:00
commit a3142ea85b
6 changed files with 109 additions and 8 deletions

View file

@ -3,6 +3,7 @@ package com.eddy.atomrelay
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.ColorStateList
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
@ -12,6 +13,7 @@ import android.widget.ImageButton
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
class MainActivity : AppCompatActivity(), BleCallbacks { class MainActivity : AppCompatActivity(), BleCallbacks {
@ -28,6 +30,8 @@ class MainActivity : AppCompatActivity(), BleCallbacks {
private lateinit var relay1Button: Button private lateinit var relay1Button: Button
private lateinit var relay2Button: Button private lateinit var relay2Button: Button
private var lastTheme: String? = null private var lastTheme: String? = null
private var originalTint1: ColorStateList? = null
private var originalTint2: ColorStateList? = null
override fun onStatusChanged(status: BleStatus) { override fun onStatusChanged(status: BleStatus) {
when (status) { when (status) {
@ -61,8 +65,8 @@ class MainActivity : AppCompatActivity(), BleCallbacks {
relay2Button.setOnTouchListener(null) relay2Button.setOnTouchListener(null)
relay1Button.setOnClickListener(null) relay1Button.setOnClickListener(null)
relay2Button.setOnClickListener(null) relay2Button.setOnClickListener(null)
relay1Button.text = getString(R.string.button_retry_scan) loadButtonLabel(relay1Button, PrefsHelper.PREF_LABEL1, R.string.button_retry_scan)
relay2Button.text = getString(R.string.button_hold) loadButtonLabel(relay2Button, PrefsHelper.PREF_LABEL2, R.string.button_hold)
relay2Button.isEnabled = false relay2Button.isEnabled = false
relay1Button.isEnabled = true relay1Button.isEnabled = true
relay1Button.setOnClickListener { relay1Button.setOnClickListener {
@ -113,6 +117,8 @@ class MainActivity : AppCompatActivity(), BleCallbacks {
recreate() recreate()
return return
} }
loadButtonLabel(relay1Button, PrefsHelper.PREF_LABEL1, R.string.button_hold)
loadButtonLabel(relay2Button, PrefsHelper.PREF_LABEL2, R.string.button_hold)
if (!manager.hasPermissions()) { if (!manager.hasPermissions()) {
requestPermissions() requestPermissions()
return return
@ -142,17 +148,20 @@ class MainActivity : AppCompatActivity(), BleCallbacks {
private fun setupRelayButton() { private fun setupRelayButton() {
relay1Button.setOnClickListener(null) relay1Button.setOnClickListener(null)
relay1Button.text = getString(R.string.button_hold) loadButtonLabel(relay1Button, PrefsHelper.PREF_LABEL1, R.string.button_hold)
originalTint1 = relay1Button.backgroundTintList
val accentColor = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.colorAccent))
relay1Button.setOnTouchListener { _, event -> relay1Button.setOnTouchListener { _, event ->
when (event.action) { when (event.action) {
MotionEvent.ACTION_DOWN -> { MotionEvent.ACTION_DOWN -> {
manager.sendRelayCommand(0x01.toByte()) manager.sendRelayCommand(0x01.toByte())
relay1Button.text = getString(R.string.button_on) relay1Button.backgroundTintList = accentColor
true true
} }
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
manager.sendRelayCommand(0x00.toByte()) manager.sendRelayCommand(0x00.toByte())
relay1Button.text = getString(R.string.button_hold) relay1Button.backgroundTintList = originalTint1
true true
} }
else -> false else -> false
@ -162,17 +171,20 @@ class MainActivity : AppCompatActivity(), BleCallbacks {
private fun setupRelay2Button() { private fun setupRelay2Button() {
relay2Button.setOnClickListener(null) relay2Button.setOnClickListener(null)
relay2Button.text = getString(R.string.button_hold) loadButtonLabel(relay2Button, PrefsHelper.PREF_LABEL2, R.string.button_hold)
originalTint2 = relay2Button.backgroundTintList
val accentColor = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.colorAccent))
relay2Button.setOnTouchListener { _, event -> relay2Button.setOnTouchListener { _, event ->
when (event.action) { when (event.action) {
MotionEvent.ACTION_DOWN -> { MotionEvent.ACTION_DOWN -> {
manager.sendRelayCommand(0x02.toByte()) manager.sendRelayCommand(0x02.toByte())
relay2Button.text = getString(R.string.button_on) relay2Button.backgroundTintList = accentColor
true true
} }
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
manager.sendRelayCommand(0x03.toByte()) manager.sendRelayCommand(0x03.toByte())
relay2Button.text = getString(R.string.button_hold) relay2Button.backgroundTintList = originalTint2
true true
} }
else -> false else -> false
@ -180,6 +192,12 @@ class MainActivity : AppCompatActivity(), BleCallbacks {
} }
} }
private fun loadButtonLabel(button: Button, prefKey: String, fallbackResId: Int) {
val prefs = PrefsHelper.getPrefs(this)
val label = prefs.getString(prefKey, "")?.trim()
button.text = if (label.isNullOrEmpty()) getString(fallbackResId) else label
}
private fun requestPermissions() { private fun requestPermissions() {
val perms = manager.getRequiredPermissions() val perms = manager.getRequiredPermissions()
ActivityCompat.requestPermissions(this, perms, 1) ActivityCompat.requestPermissions(this, perms, 1)

View file

@ -13,6 +13,8 @@ object PrefsHelper {
const val PREF_UUID = "device_uuid" const val PREF_UUID = "device_uuid"
const val PREF_SEQ = "seq_counter" const val PREF_SEQ = "seq_counter"
const val PREF_THEME = "theme" const val PREF_THEME = "theme"
const val PREF_LABEL1 = "label_relay1"
const val PREF_LABEL2 = "label_relay2"
const val SEQ_MAX = 1_000_000 const val SEQ_MAX = 1_000_000
fun applyTheme(context: Context) { fun applyTheme(context: Context) {

View file

@ -17,8 +17,11 @@ import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.util.Log import android.util.Log
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.Button import android.widget.Button
import android.widget.CheckBox import android.widget.CheckBox
import android.widget.EditText
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.RadioGroup import android.widget.RadioGroup
import android.widget.TextView import android.widget.TextView
@ -136,6 +139,7 @@ class SettingsActivity : AppCompatActivity() {
registerReceiver(usbDetachedReceiver, IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED), Context.RECEIVER_EXPORTED) registerReceiver(usbDetachedReceiver, IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED), Context.RECEIVER_EXPORTED)
setupThemeButtons() setupThemeButtons()
setupLabelEditTexts()
} }
override fun onResume() { override fun onResume() {
@ -200,6 +204,33 @@ class SettingsActivity : AppCompatActivity() {
return true return true
} }
private fun setupLabelEditTexts() {
val prefs = PrefsHelper.getPrefs(this)
val label1 = findViewById<EditText>(R.id.labelRelay1)
val label2 = findViewById<EditText>(R.id.labelRelay2)
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
label1.setText(prefs.getString(PrefsHelper.PREF_LABEL1, ""))
label2.setText(prefs.getString(PrefsHelper.PREF_LABEL2, ""))
label1.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
prefs.edit().putString(PrefsHelper.PREF_LABEL1, label1.text.toString().trim()).apply()
imm.hideSoftInputFromWindow(label1.windowToken, 0)
label1.clearFocus()
}
false
}
label2.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
prefs.edit().putString(PrefsHelper.PREF_LABEL2, label2.text.toString().trim()).apply()
imm.hideSoftInputFromWindow(label2.windowToken, 0)
label2.clearFocus()
}
false
}
}
// === Key Exchange === // === Key Exchange ===
private fun startKeyExchange() { private fun startKeyExchange() {

View file

@ -26,6 +26,7 @@
android:layout_height="200dp" android:layout_height="200dp"
android:text="1" android:text="1"
android:textSize="24sp" android:textSize="24sp"
android:textAllCaps="false"
android:enabled="false" /> android:enabled="false" />
<Button <Button
@ -35,6 +36,7 @@
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:text="2" android:text="2"
android:textSize="24sp" android:textSize="24sp"
android:textAllCaps="false"
android:enabled="false" /> android:enabled="false" />
</LinearLayout> </LinearLayout>

View file

@ -45,6 +45,49 @@
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:layout_marginBottom="16dp" /> android:layout_marginBottom="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/section_labels"
android:textSize="14sp"
android:textStyle="bold"
android:layout_marginBottom="8dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<EditText
android:id="@+id/labelRelay1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/hint_label_relay1"
android:maxLines="1"
android:inputType="text"
android:imeOptions="actionDone"
android:gravity="center" />
<EditText
android:id="@+id/labelRelay2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/hint_label_relay2"
android:maxLines="1"
android:inputType="text"
android:imeOptions="actionDone"
android:gravity="center" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"
android:layout_marginBottom="16dp" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

@ -55,6 +55,11 @@
<string name="button_close">Sluiten</string> <string name="button_close">Sluiten</string>
<string name="button_cancel">Annuleren</string> <string name="button_cancel">Annuleren</string>
<!-- Label customization -->
<string name="section_labels">Knoptekst</string>
<string name="hint_label_relay1">Relay 1</string>
<string name="hint_label_relay2">Relay 2</string>
<!-- Theme --> <!-- Theme -->
<string name="section_theme">Weergave</string> <string name="section_theme">Weergave</string>
<string name="theme_system">Systeem</string> <string name="theme_system">Systeem</string>