Building simple and effective login forms on Android

Sammy Odenhoven
AndroidPub
Published in
4 min readJun 6, 2018

--

This article describes a simple and effective way to achieve fancy “form validation” in Android, using custom View classes, custom drawable states and Android’s support library. The goal is to create one custom View class, that shows the correct UI depending on whether the View is in a (custom defined) error state. That UI can be set through drawables, and hence makes the view easily reusable and configurable in different AppThemes.

Suppose a form for signing up for an account with the following requirements:

  • A field to fill in an email address
  • A field to fill in a password
  • A password visibility toggle that toggles the password visibility
  • Furthermore we want our fields to have an error state that is activated when the input doesn’t conform with email- and password validation respectively

All of this logic can easily be put in the Presenter controlling this specific screen, but that doesn’t make it very reusable. We want to achieve this through 100% View-related logic: View classes and StateListDrawables.

Our form fields, with different states: no error, error, password visible, password invisible.

Custom StateListDrawables

StateListDrawables are XML files that contain a number of graphic images for different states of the drawable. A common example of this is an “activated” and “deactivated” state of a button. The StateListDrawable would for example be:

<selector xmlns:android=”http://schemas.android.com/apk/res/android">
<item android:drawable=”@color/blue” android:state_enabled=”false” />
<item android:drawable=”@color/red”/>
</selector>

If this drawable is assigned to a Button (through android:background=”@drawable/bg_button”), then the button will be red while being in activated state (myButton.enabled = true), and blue while being in deactivated state (myButton.enabled = false). Simple, right?

The same logic can obviously be used for EditText, like in our form. However, there is no XML attribute that describes an EditText’s error-state, and so we have to create our own. We do this by adding our own stylable to attrs.xml:

<resources>
<declare-styleable name="EditTextErrorState">
<attr name="state_error" format="boolean"/>
</declare-styleable>
</resources>

Now we can create a StateListDrawable that has has a different graphic image for different state_error values.

bg_edittext.xml :

<selector xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:drawable="@drawable/grey"
app:state_error="false" />
<item android:drawable="@drawable/red_transparent"
app:state_error="true"/>
</selector>

textcolor_edittext.xml :

<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:color="@color/charcoal_grey"
app:state_error="false" />
<item android:color="@color/red"
app:state_error="true"/>
</selector>

Custom EditText classes for email validation

Next up, we want to incorporate this state-logic into a View class, so that we can set the state of a View and show the right respective drawable is shown.

Let’s start with the email field. We want this field to be in a non-error state when it’s in focus (when the user is typing text into it). When it loses focus, we validate the text filled in by the user. If the email is invalid, we set the EditText to it’s error state. If not, we set it to it’s non-error state. As we don’t want the field to become in an error state straight away, don’t update the error state if the input hasn’t been changed by user at least once.

Our (rather simple) email validator looks like this:

Which we use in our custom EmailValidationEditText View class as follows:

Let’s go through this code step by step.

  • Overriding onCreateDrawableState() allows us to inject our own states, which then become accessible by the drawables used in the view.
  • We attach an onTextChangedListener to the view, which sets a global boolean to true, in order to make sure that from now on this field will get validated and updated to a potential error state.
  • We attach an onFocusChangeListener to the view. Every time the view loses focus, we verify whether the input is valid, and refresh the drawable state.

Now all that’s left is to use this EditText in our Activity, and style it accordingly!

<com.oddhov.signupformvalidation.tools.view.EmailValidationEditText
android:id="@+id/emailAddress"
style="@style/SignupEditText"
android:layout_width="match_parent"
android:layout_height="48dp"
android:hint="@string/signup_email_hint"/>
<style name="SignupEditText" parent="Widget.AppCompat.EditText">
<item name="colorControlNormal">@color/transparent</item>
<item name="colorControlActivated">@color/transparent</item>
<item name="colorControlHighlight">@color/transparent</item>
<item name="android:paddingLeft">@dimen/d2</item>
<item name="android:gravity">center_vertical</item>
<item name="android:textColorHint">@color/light_grey</item>
<item name="android:textSize">@dimen/s16</item>
<item name="android:inputType">
textEmailAddress|textNoSuggestions</item>
<item name="android:textColor">
@drawable/textColor_editText</item>
<item name="android:background">@drawable/bg_editText</item>
</style>

Note here the textColor and background attributes. These are the drawables are responsible for changing the styling of the EditText, based on whether it is in error state or not.

Password validation

The View class used for password input and validation is generally the same as for the email. We want to make the password input visible and invisible, through a toggle. Android provides this through their support library, yay! 🎉

Meet TextInputLayout, and TextInputEditText. There are several excellent Medium posts out there that take you through the workings of these components (like this one), so I will skip that part. I just want to show you how you can easily apply the previously described logic to these components as well.

Our simple password validator:

And custom PasswordValidationTextInputEditText class:

The final result:

You can check out the full code at:
https://github.com/SammyO/SignUpFormValidation

--

--

Sammy Odenhoven
AndroidPub

develops apps at MyWallSt | 🎧🎶 | is always thinking about food | 🇳🇱🇮🇪