Issue
How can I implement phone number visual transformation in jetpack compose? I have read this article for the card number.
And I want to format my phone number like this xx xxx xx xx
Solution
You can just modify some params from the example link that you provided according to the pattern you need. You need to consider the max length you want, how many spaces you need between each section.
For example in your given link here: http://zenandroid.io/using-the-jetpack-composes-visualtransformation-to-create-a-credit-card-text-input/
- They're adding space after every 4th character in
AnnotatedString.Builder()
You need it on 1, 4, 6. - then they've added 2 spaces that's why they're adding spaces like 2,4,6 in
originalToTransformed
but you need 1,2,3 & same for deducting intransformedToOriginal
Complete code example:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AppTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Test()
}
}
}
}
}
@Composable
fun Test() {
var mobileNumber by rememberSaveable { mutableStateOf("") }
Column {
Row(modifier = Modifier.padding(all = 10.dp)) {
Text(
text = "Mobile number",
fontSize = 14.sp,
modifier = Modifier.weight(1f)
)
BasicTextField(
value = mobileNumber,
onValueChange = { mobileNumber = it },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
visualTransformation = { mobileNumberFilter(it) }
)
}
Box(
modifier = Modifier
.height(1.dp)
.padding(start = 10.dp)
.fillMaxWidth()
.background(Color.Gray)
)
Spacer(modifier = Modifier.height(20.dp))
Text(text = "Actual value:\n$mobileNumber")
}
}
const val mask = "xx xxx xx xx"
fun mobileNumberFilter(text: AnnotatedString): TransformedText {
// change the length
val trimmed =
if (text.text.length >= 9) text.text.substring(0..8) else text.text
val annotatedString = AnnotatedString.Builder().run {
for (i in trimmed.indices) {
append(trimmed[i])
if (i == 1 || i == 4 || i == 6) {
append(" ")
}
}
pushStyle(SpanStyle(color = Color.LightGray))
append(mask.takeLast(mask.length - length))
toAnnotatedString()
}
val phoneNumberOffsetTranslator = object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int {
if (offset <= 1) return offset
if (offset <= 4) return offset + 1
if (offset <= 6) return offset + 2
if (offset <= 9) return offset + 3
return 12
}
override fun transformedToOriginal(offset: Int): Int {
if (offset <= 1) return offset
if (offset <= 4) return offset - 1
if (offset <= 6) return offset - 2
if (offset <= 9) return offset - 3
return 9
}
}
return TransformedText(annotatedString, phoneNumberOffsetTranslator)
}
Output:
Answered By - Mayur Gajra
Answer Checked By - Marilyn (JavaFixing Volunteer)