I'm trying to implement visual transformation to showing formatted phone number with mask.
The problem is that the mask is dynamic, and it can be received from the backend, depending on the characters that the client has already entered, so it takes some time to receive it.
Here is my visual transformation:
class PhoneVisualTransformation(val mask: String) :
VisualTransformation {
override fun filter(text: AnnotatedString): TransformedText {
val source = text.text
val formattedPhone = source.formatByMask(mask = mask)
return TransformedText(
text = AnnotatedString(source),
offsetMapping = offsetFilter(text = formattedPhone),
)
}
private fun offsetFilter(text: String): OffsetMapping {
val numberOffsetTranslator = object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int {
val transformedOffsets = text
.mapIndexedNotNull { index, c ->
index
.takeIf { !isFormattingCharacter(c) }
?.plus(1)
}.let { offsetList ->
listOf(0) + offsetList
}
return transformedOffsets[offset]
}
override fun transformedToOriginal(offset: Int): Int {
return text
.mapIndexedNotNull { index, c ->
index.takeIf { isFormattingCharacter(c) }
}
.count { separatorIndex ->
separatorIndex < offset
}
.let { separatorCount ->
offset - separatorCount
}
}
}
return numberOffsetTranslator
}
private fun isFormattingCharacter(char: Char): Boolean {
return listOf('(', ')', '-', ' ').any { char == it }
}
}
formatByMask is extension which use redmadrobot input mask library.
InputTextField(
modifier = modifier,
input = state.phone,
visualTransformation = PhoneVisualTransformation(
mask = state.mask,
),
onValueChange = {
viewModel.onValueChange(it)
},
)
And my ViewModel:
fun onValueChange(newValue: String) {
viewModelScope.launch {
val phoneDetials = getPhoneDetailsByInput(newValue)
_state.update {
it.copy(phone = phoneDetails.phone, mask = phoneDetails.mask)
}
}
} }
getPhoneDetailsByInput() is suspend function which returns mask from backend. The problem is that offset in my OffsetMapping is always 0.
What am I doing wrong ? Perhaps I took the wrong approach altogether. Please help me.
Then compose