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

您可以在应用的文本字段中自动格式化电话号码,通过在用户输入数字时格式化电话号码来节省用户时间。请遵循以下指南自动格式化电话号码

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

版本兼容性

此实现要求您的项目 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 使用正则表达式删除所有非数字字符,并在更新 phoneNumber 状态之前将长度限制为最多 10 个字符。
  • 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 用于执行格式化。

结果

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

包含本指南的收藏集

本指南是这些经过策划的快速指南收藏集的一部分,涵盖更广泛的 Android 开发目标

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

有问题或反馈吗?

访问我们的常见问题页面,了解有关快速指南的信息,或与我们联系并告诉我们您的想法。