Search code examples
androidkotlinandroid-jetpack-composetextfield

Compose credit card format textfield


I am trying to make a credit format text field. Everything works fine until you fill up all the characters and then try to delete some. Any thoughts on what I am doing wrong?

    // XXXX-XXXX-XXXX-XXXX
var text by remember { mutableStateOf("") }
OutlinedTextField(
    value = text,
    onValueChange = {
        if(text.length <=16)
            text = it
    },
    visualTransformation = object : VisualTransformation {
        override fun filter(text: AnnotatedString): TransformedText {
            val trimmed = if (text.text.length >= 16) text.text.substring(0..15) else text.text
            var out = ""

            for (i in trimmed.indices) {
                out += trimmed[i]
                if (i % 4 == 3 && i != 15) out += "-"
            }
            return TransformedText(
                AnnotatedString(out),
                creditCardOffsetMapping
            )
        }
    }
)

// Making XXXX-XXXX-XXXX-XXXX string.
val creditCardOffsetMapping = object : OffsetMapping {
    override fun originalToTransformed(offset: Int): Int {
        if (offset <= 3) return offset
        if (offset <= 7) return offset + 1
        if (offset <= 11) return offset + 2
        if (offset <= 16) return offset + 3
        return 19
    }

    override fun transformedToOriginal(offset: Int): Int {
        if (offset <= 4) return offset
        if (offset <= 9) return offset - 1
        if (offset <= 14) return offset - 2
        if (offset <= 19) return offset - 3
        return 16
    }
}

Solution

  • The problem is in your onValueChange lamba.

    instead of this:

        onValueChange = {
            if(text.length <=16)
                text = it
        }
    

    use this:

    onValueChange = {
    
       text = it.take(16)
    }