I am trying to create a reusable NumberField component:
@Composable
fun NumberField(
value: Number?,
onNumberChange: (Number) -> Unit,
) {
TextField(
value = value?.toString() ?: "",
onValueChange = {
it.toDoubleOrNull()?.let { value ->
if (value % 1.0 == 0.0) {
onNumberChange(value.toInt())
} else {
onNumberChange(value)
}
}
},
singleLine = true,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
)
}
To be used as:
@Composable
fun NumberContent() {
val number = remember { mutableStateOf<Number?>(null) }
NumberField(value = number.value) {
number.value = it
}
}
I would like the number to be an Int or Double depending on what the user is typing. What I have above works until you try to enter a decimal number, as it seems "5.", does not parse as double. I want to allow the user to type 5. and then fill in rest. As such I don't want to add a zero after decimal automatically because that might not be the next number they want to enter. Is this the best way to go about it? I know that I can just accept any text and then try to format the text they entered later as an int or double and make them fix it then, just thought it would be nice to bundle it all in the composable.
Android Compose – Change Text to Bold To change font weight of Text composable to Bold, in Android Jetpack Compose, pass FontWeight. Bold for the optional fontWeight parameter of Text composable.
To read value entered in TextField in Android Compose, declare a variable, and assign this variable the value in the TextField whenever there is a change in the value. The same process holds for reading value entered in OutlineTextField composable.
To change font size of Text composable in Android Jetpack Compose, pass a required font size value for the optional fontSize parameter of Text composable. Make sure to import sp , as shown in the above code snippet, when you are assign fontSize property with scale-independent pixels.
You can use something like:
TextField(
value = text,
onValueChange = {
if (it.isEmpty()){
text = it
} else {
text = when (it.toDoubleOrNull()) {
null -> text //old value
else -> it //new value
}
}
},
singleLine = true,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
)
Here is an implementation that handles all stated conditions while also exposing the state to parents.
@Composable
fun NumberField(
value: Number?,
onNumberChange: (Number?) -> Unit,
) {
val number = remember { mutableStateOf(value) }
val textValue = remember(value != number.value) {
number.value = value
mutableStateOf(value?.toDouble()?.let {
if (it % 1.0 == 0.0) {
it.toInt().toString()
} else {
it.toString()
}
} ?: "")
}
val numberRegex = remember { "[-]?[\\d]*[.]?[\\d]*".toRegex() }
// for no negative numbers use "[\d]*[.]?[\d]*"
TextField(
value = textValue.value,
onValueChange = {
if (numberRegex.matches(it)) {
textValue.value = it
number.value = it.toDoubleOrNull()
onNumberChange(number.value)
}
},
singleLine = true,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
)
}
An example usage is shown below.
@Composable
fun DemoUsage() {
Column {
val number = remember { mutableStateOf<Number?>(null) }
NumberField(value = number.value) {
number.value = it
}
Button(onClick = { number.value = number.value?.toDouble()?.plus(1) }) {
Text("Increment")
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With