Automated Text Input Formatting on Android with MaskedEditText

Mithat Sinan Sarı
Hipo
Published in
3 min readJan 6, 2020

--

On one of our recent projects, we were faced with one of those seemingly simple but actually hard coding problems: Building a text input field that can automatically format and validate the input while the user is typing. After some trial and error, we ended up building an open source library to solve this issue: MaskedEditText.

Seasoned Android developers might be asking: Why do we even need a new library when there is a class called PhoneNumberFormattingTextWatcher? Our answer would be: Have you ever used it? Implementation is easy:

But let’s see how this works in a real world scenario:

Needless to say, that’s not good UX, and no self-respecting developer can ship with a solution like that. Default solution places parentheses when you don’t expect it and goes completely bonkers if you type more numbers than it expects. That’s why we need an extra library and this is how MaskedEditText came to exist.

How does it work?

It works as expected, no magic here, just good UX.

It has four options:

  • Phone Number (###) ###-####
  • Date ## / ## / ####
  • SSN Number ###-##-####
  • Custom (However you want it to be)

How to use it?

Define an edit text field in XML and its maskType. There is no default maskType, so it will give you a runtime error if maskType is not selected.

Caused by: java.lang.Exception: MaskedEditText: maskType must be selected
Define your maskType in your XML
Get the parsed value easily!

That’s it!

To use custom pattern you need to follow some rules;

  • maskPattern and returnPattern must be defined
  • Pound (#) count for maskPattern and returnPattern must be the same

Otherwise it will throw runtime exception with explanation.

Under the hood

It’s just an edit text field that doesn’t trigger itself when text is set by masker manually. And this edit text field uses a class called Masker to handle text changes. It accepts Mask (which is type of mask; date, ssn, etc.) and onTextMaskedListener. This listener is triggered when formatting is done.

Since we use kotlin, we can simply use it as below:

In MaskedEditText, when onTextChanged is triggered, we also trigger masker’s onTextChanged function. Then it triggers onTextMaskedListener.

Every mask type extends abstract Mask class.

As you can see, there is a field called returnPattern. Yes you can define your return pattern.

Phone and SSN returns only digits, date returns a string with YYYY-MM-DD pattern. You need to use fun getParsedText(maskedText: String): String? function to get parsed text. Why is return type nullable? To understand if return pattern and mask pattern matches or not. If user doesn’t fill the expected input, it returns null.

You can find whole project at the link below and all contributions are welcome!

It is also in jcenter which means you can simply add it to your project as so:

implementation 'com.hipo.maskededittext:maskededittext:1.1.0'

Thanks!

--

--