自动设置文本字段中的电话号码格式

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

  • 创建文本字段。
  • 自动设置文本字段中的数字格式。

版本兼容性

此实现要求将项目 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 可组合项,其中 onValueChange 使用正则表达式移除所有非数字字符,并将长度限制为最多 10 个字符,然后再更新 phoneNumber 状态。
  • TextFieldvisualTransformation 属性上设置了自定义 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 用于执行格式设置。

结果

文本字段中自动设置格式的电话号码
图 1. 文本字段中自动设置格式的电话号码。

包含本指南的集合

本指南属于以下精选快速入门集合,这些集合涵盖了更广泛的 Android 开发目标:

文字对任何界面都属于核心内容。了解在应用中呈现文本的不同方式,以提供愉悦的用户体验。
了解如何实现用户通过输入文本和使用其他输入方式与您的应用互动的方式。

有问题或反馈

请访问我们的常见问题解答页面,了解简短指南,或与我们联系,告诉我们您的想法。