@@ -52,6 +52,7 @@ import androidx.compose.ui.graphics.Color.Companion.Cyan
5252import androidx.compose.ui.graphics.Shadow
5353import androidx.compose.ui.platform.LocalUriHandler
5454import androidx.compose.ui.res.stringResource
55+ import androidx.compose.ui.text.AnnotatedString
5556import androidx.compose.ui.text.LinkAnnotation
5657import androidx.compose.ui.text.ParagraphStyle
5758import androidx.compose.ui.text.PlatformTextStyle
@@ -64,7 +65,10 @@ import androidx.compose.ui.text.font.FontFamily
6465import androidx.compose.ui.text.font.FontStyle
6566import androidx.compose.ui.text.font.FontWeight
6667import androidx.compose.ui.text.input.KeyboardType
68+ import androidx.compose.ui.text.input.OffsetMapping
6769import androidx.compose.ui.text.input.PasswordVisualTransformation
70+ import androidx.compose.ui.text.input.TransformedText
71+ import androidx.compose.ui.text.input.VisualTransformation
6872import androidx.compose.ui.text.style.Hyphens
6973import androidx.compose.ui.text.style.LineBreak
7074import androidx.compose.ui.text.style.LineHeightStyle
@@ -765,6 +769,72 @@ fun BasicMarqueeSample() {
765769}
766770// [END android_compose_text_marquee]
767771
772+ // [START android_compose_text_auto_format_phone_number_textfieldconfig]
773+ @Composable
774+ fun PhoneNumber () {
775+ var phoneNumber by rememberSaveable { mutableStateOf(" " ) }
776+ val numericRegex = Regex (" [^0-9]" )
777+ TextField (
778+ value = phoneNumber,
779+ onValueChange = {
780+ // Remove non-numeric characters.
781+ val stripped = numericRegex.replace(it, " " )
782+ phoneNumber = if (stripped.length >= 10 ) {
783+ stripped.substring(0 .. 9 )
784+ } else {
785+ stripped
786+ }
787+ },
788+ label = { Text (" Enter Phone Number" ) },
789+ visualTransformation = NanpVisualTransformation (),
790+ keyboardOptions = KeyboardOptions (keyboardType = KeyboardType .Number )
791+ )
792+ }
793+ // [END android_compose_text_auto_format_phone_number_textfieldconfig]
794+
795+ // [START android_compose_text_auto_format_phone_number_transformtext]
796+ class NanpVisualTransformation () : VisualTransformation {
797+
798+ override fun filter (text : AnnotatedString ): TransformedText {
799+ val trimmed = if (text.text.length >= 10 ) text.text.substring(0 .. 9 ) else text.text
800+
801+ var out = if (trimmed.isNotEmpty()) " (" else " "
802+
803+ for (i in trimmed.indices) {
804+ if (i == 3 ) out + = " ) "
805+ if (i == 6 ) out + = " -"
806+ out + = trimmed[i]
807+ }
808+ return TransformedText (AnnotatedString (out ), phoneNumberOffsetTranslator)
809+ }
810+
811+ private val phoneNumberOffsetTranslator = object : OffsetMapping {
812+
813+ override fun originalToTransformed (offset : Int ): Int =
814+ when (offset) {
815+ 0 -> offset
816+ // Add 1 for opening parenthesis.
817+ in 1 .. 3 -> offset + 1
818+ // Add 3 for both parentheses and a space.
819+ in 4 .. 6 -> offset + 3
820+ // Add 4 for both parentheses, space, and hyphen.
821+ else -> offset + 4
822+ }
823+
824+ override fun transformedToOriginal (offset : Int ): Int =
825+ when (offset) {
826+ 0 -> offset
827+ // Subtract 1 for opening parenthesis.
828+ in 1 .. 5 -> offset - 1
829+ // Subtract 3 for both parentheses and a space.
830+ in 6 .. 10 -> offset - 3
831+ // Subtract 4 for both parentheses, space, and hyphen.
832+ else -> offset - 4
833+ }
834+ }
835+ }
836+ // [END android_compose_text_auto_format_phone_number_transformtext]
837+
768838private val firaSansFamily = FontFamily ()
769839
770840val LightBlue = Color (0xFF0066FF )
0 commit comments