Jav*_*lon 6 android phone-number textfield android-jetpack-compose
如何在jetpack compose中实现电话号码可视化转换?我已经阅读了这篇文章以获取卡号。
我想像这样格式化我的电话号码xx xxx xx xx
Yel*_*sov 11
动态电话号码格式化程序。
一些使用不同掩码的示例。
@Composable
fun LoginScreen() {
var phoneNumber by rememberSaveable { mutableStateOf("") }
Column {
PhoneField(phoneNumber,
mask = "000 000 00 00",
maskNumber = '0',
onPhoneChanged = { phoneNumber = it })
Spacer(modifier = Modifier.padding(8.dp))
PhoneField(phoneNumber,
mask = "(000) 000 00 00",
maskNumber = '0',
onPhoneChanged = { phoneNumber = it })
Spacer(modifier = Modifier.padding(8.dp))
PhoneField(phoneNumber,
mask = "+7-000-000-00-00",
maskNumber = '0',
onPhoneChanged = { phoneNumber = it })
}
}
@Composable
fun PhoneField(
phone: String,
modifier: Modifier = Modifier,
mask: String = "000 000 00 00",
maskNumber: Char = '0',
onPhoneChanged: (String) -> Unit
) {
TextField(
value = phone,
onValueChange = { it ->
onPhoneChanged(it.take(mask.count { it == maskNumber }))
},
label = {
Text(text = "Phone number")
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Phone),
visualTransformation = PhoneVisualTransformation(mask, maskNumber),
modifier = modifier.fillMaxWidth(),
)
}
class PhoneVisualTransformation(val mask: String, val maskNumber: Char) : VisualTransformation {
private val maxLength = mask.count { it == maskNumber }
override fun filter(text: AnnotatedString): TransformedText {
val trimmed = if (text.length > maxLength) text.take(maxLength) else text
val annotatedString = buildAnnotatedString {
if (trimmed.isEmpty()) return@buildAnnotatedString
var maskIndex = 0
var textIndex = 0
while (textIndex < trimmed.length && maskIndex < mask.length) {
if (mask[maskIndex] != maskNumber) {
val nextDigitIndex = mask.indexOf(maskNumber, maskIndex)
append(mask.substring(maskIndex, nextDigitIndex))
maskIndex = nextDigitIndex
}
append(trimmed[textIndex++])
maskIndex++
}
}
return TransformedText(annotatedString, PhoneOffsetMapper(mask, maskNumber))
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is PhonedVisualTransformation) return false
if (mask != other.mask) return false
if (maskNumber != other.maskNumber) return false
return true
}
override fun hashCode(): Int {
return mask.hashCode()
}
}
private class PhoneOffsetMapper(val mask: String, val numberChar: Char) : OffsetMapping {
override fun originalToTransformed(offset: Int): Int {
var noneDigitCount = 0
var i = 0
while (i < offset + noneDigitCount) {
if (mask[i++] != numberChar) noneDigitCount++
}
return offset + noneDigitCount
}
override fun transformedToOriginal(offset: Int): Int =
offset - mask.take(offset).count { it != numberChar }
}
Run Code Online (Sandbox Code Playgroud)
您只需根据您需要的模式修改您提供的示例链接中的一些参数即可。您需要考虑所需的最大长度,每个部分之间需要多少空间。
例如,在您给定的链接中:http://zenandroid.io/using-the-jetpack-composes-visualtransformation-to-create-a-credit-card-text-input/
AnnotatedString.Builder()You need it on 1, 4, 6 中的每 4 个字符后添加空格。originalToTransformed,但你需要 1,2,3 和相同的来扣除transformedToOriginal完整代码示例:
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)
}
Run Code Online (Sandbox Code Playgroud)
输出:
| 归档时间: |
|
| 查看次数: |
12016 次 |
| 最近记录: |