skip to Main Content

So i’m trying to implement the top answer in this thread

StackOverflow demo

as well as follow along with the following video

YouTube demo

The app builds fine, but as soon as I click the TextField to begin inserting data the app crashes with the following error (the stack trace is far too big to copy in I think)

java.lang.IllegalStateException: OffsetMapping.transformedToOriginal returned invalid mapping: 12 -> 10 is not in range of original text [0, 0]

I simply cannot see where the issue lies as there is basically no deviation from the examples given apart from small alterations to the mask and offset to suit the format I am going for. But as far as I can see these should be ok. My code sample is as follows.

    @Composable
fun DisplayPhoneNumberTextField() {

    var mobileNo by remember {
        mutableStateOf("")
    }

    OutlinedTextField(
        value = mobileNo,
        onValueChange = { mobileNo = it},
        modifier = Modifier.fillMaxWidth(),
        placeholder = {
            Text(text = "Phone Number")
        },
        singleLine = true,
        colors = TextFieldDefaults.textFieldColors(
            focusedIndicatorColor = MaterialTheme.colors.secondary
        ),
        visualTransformation = {
            phoneNumberInputFormatter(it)
        },
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
    )
}


private fun phoneNumberInputFormatter(text : AnnotatedString) : TransformedText {

    val mask = "xxx-xxx-xxxx"

    val trimmed = if(text.text.length >= 10) text.text.substring(0..9) else text.text

    val annotatedString = AnnotatedString.Builder().run {
        for (i in trimmed.indices){
            append(trimmed[i])
            if (i == 2 || i == 5){
                append("-")
            }
        }
        pushStyle(SpanStyle(color = Color.LightGray))
        append(mask.takeLast(mask.length - length))
        toAnnotatedString()
    }

    val phoneNumberOffsetTranslator = object : OffsetMapping {
        override fun originalToTransformed(offset: Int): Int {
            if (offset <= 2) return offset
            if (offset <= 5) return offset + 1
            if (offset <= 9) return offset + 2
            return 12
        }

        override fun transformedToOriginal(offset: Int): Int {
            if (offset <= 2) return offset
            if (offset <= 5) return offset - 1
            if (offset <= 9) return offset - 2
            return 10
        }
    }

    return TransformedText(annotatedString, phoneNumberOffsetTranslator)

}

Any help would be much appreciated

2

Answers


  1. Looks like possible duplicate of this: Fatal Exception: java.lang.IllegalArgumentException offset(23) is out of bounds [0, 0] JetPack Compose OutlinedTextField
    i.e., input is empty when mapping is done

    Maybe you can try returning TransformedText like this instead of custom transformation:

    return TransformedText(annotatedString, OffsetMapping.Identity)
    

    Or, you can try solutions provided in above like i.e., return OffsetMapping.Identity when input is empty and customMapping when there is input

    Login or Signup to reply.
  2. @murphler, I could be wrong here, but I think your mask variable is getting added to the total length which is why it’s offset it crashing. Try making mask = "" and see if that helps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search