Skip to content

Instantly share code, notes, and snippets.

@carterhudson
Last active July 1, 2022 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carterhudson/b9d274d95e208352d8a71d451abbe97f to your computer and use it in GitHub Desktop.
Save carterhudson/b9d274d95e208352d8a71d451abbe97f to your computer and use it in GitHub Desktop.
class PhoneNumberVisualTransformation(locale: Locale = Locale.getDefault()) : VisualTransformation {
private val phoneNumberFormatter =
PhoneNumberUtil.getInstance().getAsYouTypeFormatter(locale.country)
override fun filter(text: AnnotatedString): TransformedText {
phoneNumberFormatter.clear()
var formatted = ""
text.forEach { formatted = phoneNumberFormatter.inputDigit(it) }
val separatorCount = formatted.count { !PhoneNumberUtils.isNonSeparator(it) }
return TransformedText(
AnnotatedString(text = formatted),
object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int =
formatted
// Cursor offsets are always 1 more than the index they are to
// the right of.
// We construct a list of non-separator indices, adding 1 to turn
// them into offsets
.mapIndexedNotNull { index, c ->
index
.takeIf { PhoneNumberUtils.isNonSeparator(c) }
?.plus(1)
}
// We want to coalesce to null if the list is empty
.takeIf { offsetList ->
offsetList.isNotEmpty()
}
// We want to support an offset of 0, so we prepend
?.let { offsetList ->
listOf(0) + offsetList
}
// We can now retrieve the transformed offset by using "offset" as our index
?.get(offset)
// If the list was empty (takeIf), we just use the un-adjusted offset
?: offset
override fun transformedToOriginal(offset: Int): Int =
formatted
// This creates a list of all separator indices
.mapIndexedNotNull { index, c ->
index.takeIf { !PhoneNumberUtils.isNonSeparator(c) }
}
// We want to count how many separators are present to the left of the offset
.count { separatorIndex ->
separatorIndex < offset
}
// We find the original offset by subtracting the number of separators
.let { separatorCount ->
offset - separatorCount
}
}
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment