Skip to content

Commit c219b3a

Browse files
committed
Improve PatchableToReducedBitmap composable: add state handling for color input, enhance keyboard actions for better UX, and prevent invalid entries
1 parent f30f23b commit c219b3a

1 file changed

Lines changed: 36 additions & 8 deletions

File tree

app/src/main/java/de/berlindroid/zepatch/ui/PatchableToReducedBitmap.kt

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,25 @@ import androidx.compose.foundation.layout.Arrangement
55
import androidx.compose.foundation.layout.Column
66
import androidx.compose.foundation.layout.fillMaxSize
77
import androidx.compose.foundation.layout.fillMaxWidth
8+
import androidx.compose.foundation.text.KeyboardActions
89
import androidx.compose.foundation.text.KeyboardOptions
910
import androidx.compose.material3.Button
1011
import androidx.compose.material3.CircularProgressIndicator
1112
import androidx.compose.material3.Text
1213
import androidx.compose.material3.TextField
1314
import androidx.compose.runtime.Composable
15+
import androidx.compose.runtime.LaunchedEffect
16+
import androidx.compose.runtime.getValue
17+
import androidx.compose.runtime.mutableStateOf
18+
import androidx.compose.runtime.saveable.rememberSaveable
19+
import androidx.compose.runtime.setValue
1420
import androidx.compose.ui.Alignment
1521
import androidx.compose.ui.Modifier
1622
import androidx.compose.ui.graphics.ImageBitmap
1723
import androidx.compose.ui.text.input.ImeAction
1824
import androidx.compose.ui.text.input.KeyboardType
1925
import androidx.compose.ui.tooling.preview.Preview
26+
import androidx.compose.ui.platform.LocalFocusManager
2027
import androidx.core.text.isDigitsOnly
2128

2229
@Composable
@@ -28,6 +35,16 @@ fun PatchableToReducedBitmap(
2835
computeReducedBitmap: () -> Unit = {},
2936
onColorCountChanged: (Int) -> Unit = {}
3037
) {
38+
// Local text state so users can clear or type partial numbers without snapping back to default
39+
var colorText by rememberSaveable { mutableStateOf(colorCount.toString()) }
40+
41+
// Keep local text in sync if colorCount changes from outside (e.g., recomputations)
42+
LaunchedEffect(colorCount) {
43+
colorText = colorCount.toString()
44+
}
45+
46+
val focusManager = LocalFocusManager.current
47+
3148
Column(
3249
modifier = modifier.fillMaxSize(),
3350
verticalArrangement = Arrangement.Center,
@@ -45,22 +62,33 @@ fun PatchableToReducedBitmap(
4562
)
4663
}
4764
TextField(
48-
value = "$colorCount",
49-
onValueChange = {
50-
if (it.isNotBlank() && it.isDigitsOnly()) {
51-
onColorCountChanged(it.toInt())
52-
} else {
53-
colorCount
65+
value = colorText,
66+
onValueChange = { new ->
67+
// Allow empty and numeric-only input
68+
if (new.isEmpty()) {
69+
colorText = ""
70+
} else if (new.isDigitsOnly()) {
71+
colorText = new
72+
new.toIntOrNull()?.let { onColorCountChanged(it) }
5473
}
74+
// ignore non-digit edits
5575
},
5676
label = { Text("How many colors do you need?") },
5777
keyboardOptions = KeyboardOptions.Default.copy(
5878
keyboardType = KeyboardType.Number,
59-
imeAction = ImeAction.Go
79+
imeAction = ImeAction.Done
80+
),
81+
keyboardActions = KeyboardActions(
82+
onDone = {
83+
if (colorText.isNotEmpty()) {
84+
focusManager.clearFocus()
85+
computeReducedBitmap()
86+
}
87+
}
6088
)
6189
)
6290

63-
Button(onClick = computeReducedBitmap) { Text("Reduce") }
91+
Button(enabled = colorText.isNotEmpty(), onClick = computeReducedBitmap) { Text("Reduce") }
6492

6593
reducedImage?.let {
6694
Image(

0 commit comments

Comments
 (0)