RedMadRobot / input-mask-android

User input masking library repo.
MIT License
1.22k stars 116 forks source link

Bug when using affine masks, and using setText() #101

Closed thalisvilela closed 1 year ago

thalisvilela commented 4 years ago

Prerequisites

Describe the bug

When using affine masks with strategy AffinityCalculationStrategy.CAPACITY and setting the text via code, the wrong mask is applied.

Steps to reproduce the behaviour:

MaskedTextChangedListener.installOn(binding.cpfInput,
            "[00].[000].[000]/[0000]-[00]", //14 digit
            listOf("[000].[000].[000]-[00]"), //11 digit
            AffinityCalculationStrategy.CAPACITY)

setText("08219031633111") <- 14 digits produces the result: 082.190.316-33 <-11 digits

It doesn't matter if i use EditText->setText() or MaskedTextChangedListener->setText(), nor using databindig. The result is the same. However, if i setText() with 15 digits , the 14 digit mask is applied correctly and the last extra digit is cropped out.

Expected behaviour setText("08219031633111") <- 14 digit should produce the result: 08.219.031/6331-11

Actual behaviour setText("08219031633111") produces the result: 082.190.316-33 Typing the text applies the right mask.

taflanidi commented 4 years ago

Hey @thalisvilela! Thanks for your report.

While I'm looking into it, could you please try switching to the AffinityCalculationStrategy. EXTRACTED_VALUE_CAPACITY and let me know the results?

thalisvilela commented 4 years ago

Hello @taflanidi , When using AffinityCalculationStrategy. EXTRACTED_VALUE_CAPACITY, the right mask is applied upon setText(). However, once you delete a single char, the mask collapses to the "smaller" and gets stuck, i mean, you keep typing, but the wider mask doesn't get applied. If you start with blank text, the behavior is the same, only the "smaller" mask gets applied.

thtmorais commented 1 year ago

@thalisvilela você conseguiu resolver este problema?

thalisvilela commented 1 year ago

@thtmorais demorei achar o projeto que utilizei essa library, mas achei! Fiz uma boa e velha gambiarra:

Meu layout ficou assim, perceba que criei doid bindings, mascara e mascaraSecundaria

<com.google.android.material.textfield.TextInputLayout
        android:id="@+id/cpf"
        style="@style/textFieldOutlined"
        error='@{vm.validator.getValidation("cpfCnpj")}'
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        app:layout_constraintEnd_toEndOf="@+id/name"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@+id/name"
        app:layout_constraintTop_toBottomOf="@+id/name">

        <com.google.android.material.textfield.TextInputEditText
            mascara='@{"[00].[000].[000]/[0000]-[00]"}'
            mascaraSecundaria='@{"[000].[000].[000]-[00]"}'
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:digits="0123456789 .-/"
            android:hint="CPF / CNPJ"
            android:imeOptions="actionDone"
            android:inputType="number"
            android:text="@={vm.creditCard.cpfCnpj}" />

</com.google.android.material.textfield.TextInputLayout>

E na definição do meu bindingAdapter eu tô usando uma lógica que sinceramente não me lembro mais como funciona, nem como eu cheguei nessa solução, já fazem 3 anos.

@BindingAdapter(value = ["mascara", "mascaraSecundaria"], requireAll = false)
fun applyMask(view: EditText, mascara: String, mascaraSecundaria: String?) {
    var buffer = view.text.toString()
    view.setText("")
    if (mascaraSecundaria != null) {
        MaskedTextChangedListener.installOn(
            view,
            mascara,
            listOf(mascaraSecundaria),
            AffinityCalculationStrategy.CAPACITY
        ).setText(buffer)

    } else MaskedTextChangedListener.installOn(view, mascara).setText(buffer)

}

Espero ter te ajudado! Éh noiz!!

thtmorais commented 1 year ago

I solved it doing:

binding.textInputEditTextCpfCnpj.inputType = InputType.TYPE_CLASS_NUMBER
binding.textInputEditTextCpfCnpj.keyListener = DigitsKeyListener.getInstance("0123456789-./")

val cpfCnpjMask = MaskedTextChangedListener("[00].[000].[000]/[0000]-[00]", binding.textInputEditTextCpfCnpj)
it.cpfCnpj?.let { cpfCnpj -> cpfCnpjMask.setText(cpfCnpj, binding.textInputEditTextCpfCnpj, false) }
cpfCnpjMask.affineFormats = listOf("[000].[000].[000]-[00]")
cpfCnpjMask.affinityCalculationStrategy = AffinityCalculationStrategy.CAPACITY
cpfCnpjMask.autocomplete = false

binding.textInputEditTextCpfCnpj.addTextChangedListener(cpfCnpjMask)
binding.textInputEditTextCpfCnpj.onFocusChangeListener = cpfCnpjMask

Note that before inserting an 'afineFormats' I entered my information, so that the first format can be applied.

taflanidi commented 1 year ago

Closing due to inactivity; feel free to reopen should you have any questions.