Formatting a UITextField for credit card input like (xxxx xxxx xxxx xxxx)

前端 未结 28 2117
长情又很酷
长情又很酷 2020-11-28 01:19

I want to format a UITextField for entering a credit card number into such that it only allows digits to be entered and automatically inserts spaces so that the

28条回答
  •  隐瞒了意图╮
    2020-11-28 02:02

    Here is a Kotlin answer based off of Mark Amery

    fun formatCardNumber(cardNumber: String): String {
        var trimmedCardNumber = cardNumber.replace(" ","")
    
        // UATP cards have 4-5-6 (XXXX-XXXXX-XXXXXX) format
        val is456 = trimmedCardNumber.startsWith("1")
    
        // These prefixes reliably indicate either a 4-6-5 or 4-6-4 card. We treat all these
        // as 4-6-5-4 to err on the side of always letting the user type more digits.
        val is465 = listOf("34", "37", "300", "301", "302", "303", "304", "305", "309", "36", "38", "39")
                .any { trimmedCardNumber.startsWith(it) }
    
        // In all other cases, assume 4-4-4-4.
        val is4444 = !(is456 || is465)
    
        trimmedCardNumber = if (is456 || is465) {
             trimmedCardNumber.take(cardNumberMaxLengthAmex)
        } else {
             trimmedCardNumber.take(cardNumberMaxLength)
        }
    
        var cardNumberWithAddedSpaces = ""
    
        trimmedCardNumber.forEachIndexed { index, c ->
            val needs465Spacing = is465 && (index == 4 || index == 10 || index == 15)
            val needs456Spacing = is456 && (index == 4 || index == 9 || index == 15)
            val needs4444Spacing = is4444 && index > 0 && index % 4 == 0
    
            if (needs465Spacing || needs456Spacing || needs4444Spacing) {
                cardNumberWithAddedSpaces += " "
            }
    
            cardNumberWithAddedSpaces += c
        }
    
        return cardNumberWithAddedSpaces
    }
    

    Then add a text changed listener on an edit text

    var flag = false
    
    editText.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
    
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if (flag) { 
                    flag = false 
                } else {
                    val text = formatCardNumber(s.toString())
                    flag = true
                    editText.setText(text)
                    editText.setSelection(text.count())
                }
            }
    
            override fun afterTextChanged(s: Editable?) {}
        })
    

提交回复
热议问题