Shariff
09/17/2025, 8:37 PM@Composable
fun PhoneNumberTextField(
phoneNumber: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
isError: Boolean = false
) {
val numericRegex = Regex("[^0-9]")
RadiusOutlinedTextField(
modifier = modifier,
value = phoneNumber,
onValueChange = {
val stripped = numericRegex.replace(it, "")
// Allow editing by limiting to 10 digits only during input
onValueChange(if (stripped.length > 10) {
stripped.substring(0, 10)
} else {
stripped
})
},
placeholder = "Phone Number",
singleLine = true,
visualTransformation = NanpVisualTransformation(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Phone),
isError = isError
)
}
class NanpVisualTransformation : VisualTransformation {
override fun filter(text: AnnotatedString): TransformedText {
val trimmed = if (text.text.length >= 10) text.text.substring(0..9) else text.text
var out = if (trimmed.isNotEmpty()) "(" else ""
for (i in trimmed.indices) {
if (i == 3) out += ") "
if (i == 6) out += "-"
out += trimmed[i]
}
return TransformedText(AnnotatedString(out), phoneNumberOffsetTranslator)
}
private val phoneNumberOffsetTranslator = object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int =
when (offset) {
0 -> offset
// Add 1 for opening parenthesis.
in 1..3 -> offset + 1
// Add 3 for both parentheses and a space.
in 4..6 -> offset + 3
// Add 4 for both parentheses, space, and hyphen.
else -> offset + 4
}
override fun transformedToOriginal(offset: Int): Int =
when (offset) {
0 -> offset
// Subtract 1 for opening parenthesis.
in 1..5 -> offset - 1
// Subtract 3 for both parentheses and a space.
in 6..10 -> offset - 3
// Subtract 4 for both parentheses, space, and hyphen.
else -> offset - 4
}
}
}Max
09/19/2025, 9:50 PMval numericRegex = Regex("[^0-9]") in every recomposition, pls use remember here or define somewhere outside. Also i gave your code to ChatGPT and it says your OffsetMapping calculation is wrong. I don’t want to paste LLM answers here, so maybe head over to the LLM of your choice and let them explain.
I had similar issues in the past on iOS, only on real phones it was not possible to input sth in fields. Try without all the transform calculation and it probably works