在文本字段中自动格式化电话号码

您可以在应用的文本字段中自动格式化电话号码,这可以在用户输入数字时格式化电话号码,从而节省用户的时间。按照本指南自动格式化电话号码

  • 创建文本字段。
  • 在文本字段中自动格式化数字。

版本兼容性

此实现要求您的项目 minSDK 设置为 API 级别 21 或更高。

依赖项

创建文本字段

首先,配置 TextField。此示例展示了按照北美编号计划 (NANP) 格式化的电话号码。NanpVisualTransformation 将原始数字字符串格式化为 NANP 格式,例如将 1234567890 格式化为 (123) 456-7890。

@Composable
fun PhoneNumber() {
    var phoneNumber by rememberSaveable { mutableStateOf("") }
    val numericRegex = Regex("[^0-9]")
    TextField(
        value = phoneNumber,
        onValueChange = {
            // Remove non-numeric characters.
            val stripped = numericRegex.replace(it, "")
            phoneNumber = if (stripped.length >= 10) {
                stripped.substring(0..9)
            } else {
                stripped
            }
        },
        label = { Text("Enter Phone Number") },
        visualTransformation = NanpVisualTransformation(),
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
    )
}

代码要点

  • 一个 TextField composable,其中 onValueChange 使用正则表达式移除所有非数字字符,并将长度限制为最多 10 个字符,然后更新 phoneNumber 状态。
  • TextField 具有自定义 VisualTransformation 实例,该实例设置在 visualTransformation 属性上。NanpVisualTransformation 是此处实例化的自定义类,定义在下一部分中。

在文本字段中自动格式化数字

要格式化原始数字字符串,请使用自定义 NanpVisualTransformation 类的实现

class NanpVisualTransformation : VisualTransformation {

    override fun filter(text: AnnotatedString): TransformedText {
        val trimmed = if (text.text.length >= 10) text.text.substring(0..9) else text.text

        var out = if (trimmed.isNotEmpty()) "(" else ""

        for (i in trimmed.indices) {
            if (i == 3) out += ") "
            if (i == 6) out += "-"
            out += trimmed[i]
        }
        return TransformedText(AnnotatedString(out), phoneNumberOffsetTranslator)
    }

    private val phoneNumberOffsetTranslator = object : OffsetMapping {

        override fun originalToTransformed(offset: Int): Int =
            when (offset) {
                0 -> offset
                // Add 1 for opening parenthesis.
                in 1..3 -> offset + 1
                // Add 3 for both parentheses and a space.
                in 4..6 -> offset + 3
                // Add 4 for both parentheses, space, and hyphen.
                else -> offset + 4
            }

        override fun transformedToOriginal(offset: Int): Int =
            when (offset) {
                0 -> offset
                // Subtract 1 for opening parenthesis.
                in 1..5 -> offset - 1
                // Subtract 3 for both parentheses and a space.
                in 6..10 -> offset - 3
                // Subtract 4 for both parentheses, space, and hyphen.
                else -> offset - 4
            }
    }
}

代码要点

  • filter() 函数在适当的位置插入非数字格式化字符。
  • phoneNumberOffsetTranslator 对象包含两个方法。一个用于映射原始字符串和格式化字符串之间的偏移量,另一个则执行反向映射。这些映射允许在用户更改文本字段中的光标位置时跳过格式化字符。
  • 格式化字符串和 phoneNumberOffsetTranslator 用作 TransformedText 实例的参数,该实例由 TextField 返回并用于执行格式化。

结果

An auto-formatted phone number in the text field
图 1. 文本字段中自动格式化的电话号码。

包含本指南的合集

本指南是以下精选快速指南合集的一部分,这些合集涵盖了更广泛的 Android 开发目标

文本是任何 UI 的核心部分。了解在应用中呈现文本的不同方法,以提供愉悦的用户体验。
了解如何实现让用户通过输入文本和使用其他输入方式与应用互动的方法。

有问题或反馈?

前往我们的常见问题页面,了解快速指南,或联系我们并告诉我们您的想法。