我正在尝试实现视觉转换以显示带有掩码的格式化电话号码。
问题在于掩码是动态的,可以从后端接收,具体取决于客户端已经输入的字符,所以接收需要一些时间。
这是我的视觉变换:
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
是使用redmadrobot输入掩码库的扩展。
InputTextField(
modifier = modifier,
input = state.phone,
visualTransformation = PhoneVisualTransformation(
mask = state.mask,
),
onValueChange = {
viewModel.onValueChange(it)
},
)
还有我的视图模型:
fun onValueChange(newValue: String) {
viewModelScope.launch {
val phoneDetials = getPhoneDetailsByInput(newValue)
_state.update {
it.copy(phone = phoneDetails.phone, mask = phoneDetails.mask)
}
}
} }
getPhoneDetailsByInput() 是挂起函数,它从后端返回掩码。 问题是我的 OffsetMapping 中的偏移量始终为 0。
我做错了什么?也许我完全采取了错误的方法。请帮助我。
fun formatPhoneNumber(phoneNumber: String): String {
// Remove all non-digit characters
val digits = phoneNumber.filter { it.isDigit() }
// Apply formatting
return buildString {
for (i in digits.indices) {
when (i) {
0 -> append('(')
3 -> append(") ")
6 -> append('-')
}
append(digits[i])
if (i == 9) break // no more digits
}
}
}
然后撰写
@Composable
有趣的电话号码文本字段(){ var 电话号码 by Remember { mutableStateOf("") }
TextField(
value = phoneNumber,
onValueChange = {
val formatted = formatPhoneNumber(it)
if (formatted.length <= 14) { // (123) 456-7890 is 14 characters long
phoneNumber = formatted
}
},
label = { Text("Phone Number") },
// Add other TextField properties as needed
)
}