Developer

Pro tip: Write a validate as you go Android TextWatcher for date entry fields

This Android EditText tutorial covers how to take user experience to the next level by writing a validate as you go TextWatcher for date entry fields.

android-logo-generic-hai.jpg

Android's EditText and companion class TextWatcher have been around since API 1.0. Both classes are quite powerful, and yet I am surprised there aren't more standard out-of-the-box validators. For example, a common occurrence is using a TextWatcher to validate a date while the user enters it. There is an android:inputType "date" attribute, but this only influences which keyboard is displayed.

The example project below shows how I typically validate user input using a TextWatcher. It requires a date in the format MM/YYYY and will auto enter the forward slash at the appropriate time. You can follow along or download and import the entire project directly into Eclipse.

1. Create a new Android project targeting Android 2.3 or better.

2. In the /res/layout folder I have added a single EditText widget to a relative layout. Setting the input type attribute will restrict the keys available on the soft keyboard presented when the field receives focus.

activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:layout_margin="40dp"
        android:layout_centerInParent="true"
        android:id="@+id/date_entry_field"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="12sp"
        android:inputType="date"
        android:hint="Exp. MM/YYYY"/>

</RelativeLayout>

3. In the /src/MainActivity.java file I implemented the custom TextWatcher. The majority of the code is focused on chunking up the date into a year and a month and validating the individual parts. It's important to reset the displayed error messaging by calling setError(null) any time the watcher gets invoked and no error condition is hit.

MainActivity.java
package com.authorwjf.datevalidatingedittext;

import java.util.Calendar;

import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.app.Activity;

public class MainActivity extends Activity {

	private EditText mDateEntryField;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mDateEntryField = (EditText) findViewById(R.id.date_entry_field);
		mDateEntryField.addTextChangedListener(mDateEntryWatcher);
	}
	
	private TextWatcher mDateEntryWatcher = new TextWatcher() {
		
		@Override
	    public void onTextChanged(CharSequence s, int start, int before, int count) {
	        String working = s.toString();
	        boolean isValid = true;
	        if (working.length()==2 && before ==0) {
	        	if (Integer.parseInt(working) < 1 || Integer.parseInt(working)>12) {
	        		isValid = false;
	            } else {
	            	working+="/";
	            	mDateEntryField.setText(working);
	            	mDateEntryField.setSelection(working.length());
	            }
	       } 
	        else if (working.length()==7 && before ==0) {
	    	   String enteredYear = working.substring(3);
	    	   int currentYear = Calendar.getInstance().get(Calendar.YEAR);
	           if (Integer.parseInt(enteredYear) < currentYear) {
	        	   isValid = false;
	           }
	       } else if (working.length()!=7) {
	    	   isValid = false;
	       }
	       
	       if (!isValid) {
	        	mDateEntryField.setError("Enter a valid date: MM/YYYY");
	       } else {
	    	   mDateEntryField.setError(null);
	       }
	       	    
		}

		@Override
		public void afterTextChanged(Editable s) {}

		@Override
		public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
		 
	};

}

There you have it. When you run the APK on a device or an emulator, you will be prompted to enter a date, and the results will be validated on-the-fly as you type.

androidtextvalidator060514.png

It is a powerful feedback mechanism to the user, and the technique could easily be applied to much more than just dates. I don't think anyone will disagree that there is little room left for round-trip validation on the mobile front. TextWatcher is a great way to take your user experience to the next level.

Also read

About

William J Francis began programming computers at age eleven. Specializing in embedded and mobile platforms, he has more than 20 years of professional software engineering under his belt, including a four year stint in the US Army's Military Intellige...

0 comments

Editor's Picks