我想为血压单位屏蔽EditText,例如(### / ###)。

值可以是2digits/2digits3digits/3digits3digits/2digits2digits/3digits

目前,我正在使用下面的代码,该代码对于2digits/2digits3digits/3digits3digits/2digits不适用于2digits/3digits

这是我的代码:

import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
import android.widget.EditText
import com.google.android.material.textfield.TextInputLayout

object EditTextBPMask {
    private const val mask22 = "##/##"
    private const val mask32 = "###/##"
    private const val mask33 = "###/###"

    fun unmask(s: String): String {
        return s.replace("[^0-9]*".toRegex(), "")
    }

    fun insert(editText: EditText): TextWatcher {
        return object : TextWatcher {
            var isUpdating: Boolean = false
            var old = ""

            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                val str = unmask(s.toString())
                val mask: String
                val defaultMask = getDefaultMask(str)
                mask = when (str.length) {
                    6 -> mask33
                    5 -> mask32
                    else -> defaultMask
                }

                var mascara = ""
                if (isUpdating) {
                    old = str
                    isUpdating = false
                    return
                }
                var i = 0
                for (m in mask.toCharArray()) {
                    if (m != '#' && str.length > old.length || m != '#' && str.length < old.length && str.length != i) {
                        mascara += m
                        continue
                    }

                    try {
                        mascara += str[i]
                    } catch (e: Exception) {
                        break
                    }

                    i++
                }
                isUpdating = true
                editText.setText(mascara)
                editText.setSelection(mascara.length)
                /*if (isValid(editText)) {
                    editText.error = null
                }
                else {
                    editText.error = "Incorrect value!"
                }*/
            }

            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
            override fun afterTextChanged(s: Editable) {}
        }
    }

    private fun getDefaultMask(str: String): String {
        var defaultMask = mask22
        if (str.length > 6) {
            defaultMask = mask33
        }
        return defaultMask
    }

    fun isValid(editText: EditText): Boolean {
        return if (!TextUtils.isEmpty(editText.text.toString())) {
            unmask(editText.text.toString()).length > 3
        }
        else {
            false
        }
    }

}

最佳答案

如果正确完成,您尝试实现的内容最终将需要您使用regular expressions中的状态机。

粗略地看,您的解决方案缺少一些关键点,例如处理光标不在字符串末尾的情况;因此,您的解决方案也无法正确处理从剪贴板粘贴的内容。

接下来,必须使用::afterTextChanged方法及其Editable变量,以便在“键入”中在“ cc”中进行更改,同时输入用户信息。

我希望鼓励您采用既定的解决方案,其中有很多。我看到您的项目中已经有了Kotlin运行时,因此您可以引入RedMadRobot/input-mask-android之类的库。该库允许根据用户输入在格式之间进行切换,并且我不得不提到我是它的维护者,所以请随时询问有关其用法的任何问题。

其他荣誉提名:


pinball83/Masked-Edittext
santalu/mask-edittext
egslava/edittext-mask
TinkoffCreditSystems/decoro
PaXLiCh/FormattEditText


-尽管我不确定这些参数中的任何一个是否可以使用不同长度的值来实际处理您的特殊情况。

关于java - 使用TextWatcher的EditText的动态蒙版(用于血压单位),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57374589/

10-09 12:57