input-mask-android icon indicating copy to clipboard operation
input-mask-android copied to clipboard

Bug when using affine masks, and using setText()

Open thalisvilela opened this issue 5 years ago • 2 comments

Prerequisites

  • [x] Put an X between the brackets on this line if you have done all of the following:
    • read our Wiki;
    • read the entire Known issues section;
    • checked that my issue isn't already filled;
    • searched StackOverflow's input-mask tag for similar problems.

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.

thalisvilela avatar Mar 12 '20 21:03 thalisvilela

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?

taflanidi avatar Mar 15 '20 17:03 taflanidi

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.

thalisvilela avatar Mar 16 '20 11:03 thalisvilela

@thalisvilela você conseguiu resolver este problema?

thtmorais avatar Jan 19 '23 21:01 thtmorais

@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!!

thalisvilela avatar Jan 20 '23 05:01 thalisvilela

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.

thtmorais avatar Feb 01 '23 16:02 thtmorais

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

taflanidi avatar Apr 16 '23 15:04 taflanidi