Date Mask in Edittext

Asked

Viewed 6,177 times

4

How to put date mask on EditText android, so that stay dd/mm/aaaa ?

  • Please [Edit] ask and add a [mcve].

3 answers

5

I usually wear one Masked Edittext in this case, where the component does everything for us.

Just take a look at Git https://github.com/VicMikhailau/MaskedEditText

In your case it would look something like this:

  <com.vicmikhailau.maskededittext.MaskedEditText
        android:id="@+id/initial_date"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        app:mask="##/##/####"
        android:inputType="date" />

Note the attribute mask, is he who will edit as needed.

EDIT

Nowadays I use a class in Kotlin to treat this, which is very similar to what Viana posted below. Step for it as parameter Edit text and type of mask in format ##/##/####. Just follow her code:

 class MyMaskEditText(var editText: EditText, protected var mMask: String) : TextWatcher {


private var isUpdating: Boolean = false
protected var mOldString = ""
internal var befores = ""

override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
    befores = s.toString().replace("[^\\d]".toRegex(), "")

}

override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
    var str = s.toString().replace("[^\\d]".toRegex(), "")

    if (str.length == 0) {
        return
    }

    if (before == 1 && befores.length > 0 && !isUpdating) {
        val last = befores.substring(befores.length, befores.length)
        val rep = last.replace("(", "").replace(")", "").replace(" ", "").replace("-", "")
        if (rep.length == 0) {
            str = str.substring(0, befores.length - 1)
        }
    }


    val mask = StringBuilder()
    if (isUpdating) {
        mOldString = str
        isUpdating = false
        return
    }
    var i = 0
    for (m in mMask.toCharArray()) {
        if (m != '#') {
            mask.append(m)
            continue
        }
        try {
            mask.append(str[i])
        } catch (e: Exception) {
            break
        }

        i++
    }
    isUpdating = true
    val x = mask.toString()
    editText.setText(x)
    editText.setSelection(mask.length)

}

override fun afterTextChanged(s: Editable) {
}
 }

To use, you can create an Extension to make it easier to view.

fun EditText.myCustomMask(mask: String) {
addTextChangedListener(MyMaskEditText(this, mask))}

2

Basically Android does not offer a native class for this type of action, so it is possible to do this using a combination of numbers and special characters.

There are some libs that can do this, like:

However, the basic rule that these libs may be using is: use method addTextChangeListener to verify what is being typed in the text field, EditText. In this way, perform some action every time the hearer gets some change.

See below the class Mask, in which it has a method insert which takes the desired mask as a parameter (##/##/####) and the EditText and does the treatment using regular expression.

public abstract class Mask {

    public static TextWatcher insert(final String mask, final EditText et) {
        return new TextWatcher() {
            boolean isUpdating;
            String oldTxt = "";
            public void onTextChanged(
                CharSequence s, int start, int before,int count) {
                String str = Mask.unmask(s.toString());
                String maskCurrent = "";
                if (isUpdating) {
                    oldTxt = str;
                    isUpdating = false;
                    return;
                }
                int i = 0;
                for (char m : mask.toCharArray()) {
                    if (m != '#' && str.length() > oldTxt.length()) {
                        maskCurrent += m;
                        continue;
                    }
                    try {
                        maskCurrent += str.charAt(i);
                    } catch (Exception e) {
                        break;
                    }
                    i++;
                }
                isUpdating = true;
                et.setText(maskCurrent);
                et.setSelection(maskCurrent.length());
            }
            public void beforeTextChanged(
                CharSequence s, int start, int count, int after) {}
            public void afterTextChanged(Editable s) {}
        };
    }
    private static String unmask(String s) {
        return s.replaceAll("[.]", "").replaceAll("[-]", "")
                .replaceAll("[/]", "").replaceAll("[(]", "")
                .replaceAll("[)]", "");
    }
}

How to use:

EditText etDate = (EditText) findViewById(R.id.etDate);
etDate.addTextChangedListener(Mask.insert("##/##/####", etDate));

See also that answer in Soen in which it has a solution very close to this.

Here also in the question about CPF/Cnpj Mask in Edittext has a solution that suits you, just modify the desired mask.

1

I preferred to write my code. It’s just a simple function, just paste and use. Obs: It’s in Kotlin.

Create the following function:

fun dateWatcher( editText:EditText) {

    var oldString : String = ""

    editText.addTextChangedListener(object : TextWatcher {
        var changed: Boolean = false

        override fun afterTextChanged(p0: Editable?) {

            changed = false



        }

        override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) 
        {
            //changed=false
            editText.setSelection(p0.toString().length)
        }

        @SuppressLint("SetTextI18n")
        override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {

            var str: String = p0.toString()

            if (str != null) {

                if (oldString.equals(str)) {
                    //significs que o user esta apagando
                    //do Nothing

                } else if (str.length == 2) {  //  xx
                    var element0: String = str.elementAt(0).toString()
                    var element1: String = str.elementAt(1).toString()
                    str = element0 + element1 + "/"
                    editText.setText(str)
                    oldString = element0 + element1
                    editText.setSelection(str.length)

                } else if (str.length == 5) { //  xx/xx

                    var element0: String = str.elementAt(0).toString() //x
                    var element1: String = str.elementAt(1).toString() //-x
                    var element2: String = str.elementAt(2).toString() //--/
                    var element3: String = str.elementAt(3).toString() //--/x
                    var element4: String = str.elementAt(4).toString() //--/-x

                    str = element0 + element1 + element2 + element3 + element4 + "/"
                    editText.setText(str)
                    oldString = element0 + element1 + element2 + element3 + element4
                    editText.setSelection(str.length)

                } else if (str.length > 8) { // este exemplo é para data no formato xx/xx/xx. Se você quer usar xx/xx/xxxx mudar para if (str.length >10). O resto do código permanece o mesmo.

                    str = str.substring(0, str.length - 1)
                    editText.setText(str)
                    editText.setSelection(str.length)

                }


            }

        }
    })
}

To use this method do so:

dateWatcher(seuEditTextAqui)
  • The code is good, but the question was asked in java. It’s always good to respect tags, even if merging Java and Kotlin is just the job of compiling an extra class.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.