Tự động định dạng số điện thoại trong trường văn bản
Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang
Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
Bạn có thể tự động định dạng số điện thoại trong trường văn bản trong ứng dụng, giúp người dùng tiết kiệm thời gian bằng cách định dạng số điện thoại khi họ nhập các chữ số. Hãy làm theo hướng dẫn này để tự động định dạng số điện thoại:
Tạo trường văn bản.
Tự động định dạng số trong trường văn bản.
Khả năng tương thích của phiên bản
Phương thức triển khai này yêu cầu bạn phải đặt minSDK của dự án thành API cấp 21 trở lên.
Phần phụ thuộc
Tạo trường văn bản
Trước tiên, hãy định cấu hình TextField. Ví dụ này cho thấy một số điện thoại được định dạng theo Quy hoạch số điện thoại Bắc Mỹ (NANP).NanpVisualTransformation định dạng một chuỗi số thô thành NANP, ví dụ:
1234567890 thành (123) 456-7890.
Thành phần kết hợp TextField, trong đó onValueChange sử dụng biểu thức chính quy để xoá tất cả ký tự không phải số và giới hạn độ dài ở mức tối đa là 10 ký tự trước khi cập nhật trạng thái phoneNumber.
TextField có một thực thể VisualTransformation tuỳ chỉnh được đặt trên thuộc tính visualTransformation. NanpVisualTransformation, lớp tuỳ chỉnh được tạo bản sao tại đây, được xác định trong phần sau.
Tự động định dạng số trong trường văn bản
Để định dạng một chuỗi số thô, hãy sử dụng cách triển khai lớp NanpVisualTransformation tuỳ chỉnh:
classNanpVisualTransformation:VisualTransformation{overridefunfilter(text:AnnotatedString):TransformedText{valtrimmed=if(text.text.length>=10)text.text.substring(0..9)elsetext.textvarout=if(trimmed.isNotEmpty())"("else""for(iintrimmed.indices){if(i==3)out+=") "if(i==6)out+="-"out+=trimmed[i]}returnTransformedText(AnnotatedString(out),phoneNumberOffsetTranslator)}privatevalphoneNumberOffsetTranslator=object:OffsetMapping{overridefunoriginalToTransformed(offset:Int):Int=when(offset){0->offset// Add 1 for opening parenthesis.in1..3->offset+1// Add 3 for both parentheses and a space.in4..6->offset+3// Add 4 for both parentheses, space, and hyphen.else->offset+4}overridefuntransformedToOriginal(offset:Int):Int=when(offset){0->offset// Subtract 1 for opening parenthesis.in1..5->offset-1// Subtract 3 for both parentheses and a space.in6..10->offset-3// Subtract 4 for both parentheses, space, and hyphen.else->offset-4}}}
Hàm filter() chèn các ký tự định dạng không phải số ở các vị trí thích hợp.
Đối tượng phoneNumberOffsetTranslator chứa hai phương thức. Một hàm ánh xạ độ dời giữa chuỗi gốc và chuỗi đã định dạng, còn hàm còn lại thực hiện ánh xạ ngược. Các ánh xạ này cho phép bỏ qua các ký tự định dạng khi người dùng thay đổi vị trí con trỏ trong trường văn bản.
Chuỗi được định dạng và phoneNumberOffsetTranslator được dùng làm đối số cho một thực thể TransformedText được trả về và sử dụng bởi TextField để thực hiện việc định dạng.
Kết quả
Hình 1. Số điện thoại được định dạng tự động trong trường văn bản.
Các bộ sưu tập chứa hướng dẫn này
Hướng dẫn này là một phần của các bộ sưu tập Hướng dẫn nhanh được tuyển chọn này, bao gồm các mục tiêu phát triển Android rộng hơn:
Văn bản hiển thị
Văn bản là phần chính của mọi giao diện người dùng. Tìm hiểu các cách khác nhau để trình bày văn bản trong ứng dụng nhằm mang lại trải nghiệm thú vị cho người dùng.
Nội dung và mã mẫu trên trang này phải tuân thủ các giấy phép như mô tả trong phần Giấy phép nội dung. Java và OpenJDK là nhãn hiệu hoặc nhãn hiệu đã đăng ký của Oracle và/hoặc đơn vị liên kết của Oracle.
Cập nhật lần gần đây nhất: 2025-02-06 UTC.
[null,null,["Cập nhật lần gần đây nhất: 2025-02-06 UTC."],[],[],null,["# Auto-format a phone number in a text field\n\n\u003cbr /\u003e\n\nYou can auto format a phone number in a text field in your app, saving users\ntime by formatting the phone number as they input digits. Follow this guidance\nto auto format a phone number:\n\n- Create the text field.\n- Auto-format a number in the text field.\n\nVersion compatibility\n---------------------\n\nThis implementation requires that your project minSDK be set to API level 21 or\nhigher.\n\n### Dependencies\n\n### Kotlin\n\n\u003cbr /\u003e\n\n```kotlin\n implementation(platform(\"androidx.compose:compose-bom:2025.08.00\"))\n implementation(\"androidx.compose.material3:material3\")\n \n```\n\n\u003cbr /\u003e\n\n### Groovy\n\n\u003cbr /\u003e\n\n```groovy\n implementation platform('androidx.compose:compose-bom:2025.08.00')\n implementation 'androidx.compose.material3:material3'\n \n```\n\n\u003cbr /\u003e\n\nCreate the text field\n---------------------\n\nFirst, configure the [`TextField`](/reference/kotlin/androidx/compose/material/package-summary#TextField(androidx.compose.ui.text.input.TextFieldValue,kotlin.Function1,androidx.compose.ui.Modifier,kotlin.Boolean,kotlin.Boolean,androidx.compose.ui.text.TextStyle,kotlin.Function0,kotlin.Function0,kotlin.Function0,kotlin.Function0,kotlin.Boolean,androidx.compose.ui.text.input.VisualTransformation,androidx.compose.foundation.text.KeyboardOptions,androidx.compose.foundation.text.KeyboardActions,kotlin.Boolean,kotlin.Int,kotlin.Int,androidx.compose.foundation.interaction.MutableInteractionSource,androidx.compose.ui.graphics.Shape,androidx.compose.material.TextFieldColors)). This example shows a phone number\nformatted per the North American Numbering Plan\n(NANP).`NanpVisualTransformation` formats a raw string of numbers to NANP, eg.\n1234567890 to (123) 456-7890.\n\n\n```kotlin\n@Composable\nfun PhoneNumber() {\n var phoneNumber by rememberSaveable { mutableStateOf(\"\") }\n val numericRegex = Regex(\"[^0-9]\")\n TextField(\n value = phoneNumber,\n onValueChange = {\n // Remove non-numeric characters.\n val stripped = numericRegex.replace(it, \"\")\n phoneNumber = if (stripped.length \u003e= 10) {\n stripped.substring(0..9)\n } else {\n stripped\n }\n },\n label = { Text(\"Enter Phone Number\") },\n visualTransformation = NanpVisualTransformation(),\n keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)\n )\n}https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/text/TextSnippets.kt#L797-L816\n```\n\n\u003cbr /\u003e\n\n### Key points about the code\n\n- A `TextField` composable where the `onValueChange` uses a regular expression to remove all non-numeric characters and limits the length to a maximum of 10 characters before updating the `phoneNumber` state.\n- The `TextField` has a custom [`VisualTransformation`](/reference/kotlin/androidx/compose/ui/text/input/VisualTransformation) instance set on the `visualTransformation` attribute. `NanpVisualTransformation`, the custom class instantiated here, is defined in the following section.\n\nAuto-format a number in the text field\n--------------------------------------\n\nTo format a raw string of numbers, use the implementation of the custom\n`NanpVisualTransformation` class:\n\n\n```kotlin\nclass NanpVisualTransformation : VisualTransformation {\n\n override fun filter(text: AnnotatedString): TransformedText {\n val trimmed = if (text.text.length \u003e= 10) text.text.substring(0..9) else text.text\n\n var out = if (trimmed.isNotEmpty()) \"(\" else \"\"\n\n for (i in trimmed.indices) {\n if (i == 3) out += \") \"\n if (i == 6) out += \"-\"\n out += trimmed[i]\n }\n return TransformedText(AnnotatedString(out), phoneNumberOffsetTranslator)\n }\n\n private val phoneNumberOffsetTranslator = object : OffsetMapping {\n\n override fun originalToTransformed(offset: Int): Int =\n when (offset) {\n 0 -\u003e offset\n // Add 1 for opening parenthesis.\n in 1..3 -\u003e offset + 1\n // Add 3 for both parentheses and a space.\n in 4..6 -\u003e offset + 3\n // Add 4 for both parentheses, space, and hyphen.\n else -\u003e offset + 4\n }\n\n override fun transformedToOriginal(offset: Int): Int =\n when (offset) {\n 0 -\u003e offset\n // Subtract 1 for opening parenthesis.\n in 1..5 -\u003e offset - 1\n // Subtract 3 for both parentheses and a space.\n in 6..10 -\u003e offset - 3\n // Subtract 4 for both parentheses, space, and hyphen.\n else -\u003e offset - 4\n }\n }\n}https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/text/TextSnippets.kt#L820-L859\n```\n\n\u003cbr /\u003e\n\n### Key points about the code\n\n- The `filter()` function inserts the non-numeric formatting characters at the appropriate places.\n- The `phoneNumberOffsetTranslator` object contains two methods. One maps the offsets between the original string and the formatted one, and the other does the reverse mapping. These mappings enable the skipping of the formatting characters when the user changes the cursor location in the text field.\n- The formatted string and `phoneNumberOffsetTranslator` are used as arguments for a `TransformedText` instance that is returned and used by the `TextField` to perform the formatting.\n\nResults\n-------\n\n**Figure 1.** An auto-formatted phone number in the text field.\n\nCollections that contain this guide\n-----------------------------------\n\nThis guide is part of these curated Quick Guide collections that cover\nbroader Android development goals: \n\n### Display text\n\nText is a central piece of any UI. Find out different ways you can present text in your app to provide a delightful user experience. \n[Quick guide collection](/develop/ui/compose/quick-guides/collections/display-text) \n\n### Request user input\n\nLearn how to implement ways for users to interact with your app by entering text and using other means of input. \n[Quick guide collection](/develop/ui/compose/quick-guides/collections/request-user-input) \n\nHave questions or feedback\n--------------------------\n\nGo to our frequently asked questions page and learn about quick guides or reach out and let us know your thoughts. \n[Go to FAQ](/quick-guides/faq) [Leave feedback](https://issuetracker.google.com/issues/new?component=1573691&template=1993320)"]]