Android AutoCompleteTextView SetOnFocusChangeListener Example


Sound / system

In every day programming we encounter new problems, and in search of solution to those we head to internet. While developing an app for Truiton on Android I also encountered a problem. I had a long list of countries from which I had to force user to select one. To solve this, I used Andorid’s AutoCompleteTextView with an OnFocusChangeListener. This OnFocusChangeListener in Android AutoCompleteTextView is set by SetOnFocusChangeListener method of View class. In this Android AutoCompleteTextView SetOnFocusChangeListener example I would also explain why this approach is better than others.

If we have to force the user to select an item from AutoCompleteTextView suggestions list, another approach is also available. For that we need to utilize addTextChangedListener and TextWatcher() methods. But this approach has a major disadvantage, that all of its three methods afterTextChanged, beforeTextChanged, onTextChanged are invoked every-time there is a change in text. This clearly is a processing overhead therefore its not suitable for our scenario.

Coming back to our original Android AutoCompleteTextView SetOnFocusChangeListener Example, I believe this is the correct way to restrict a user, to select from suggestions list. So lets begin, In this example I am going to create a layout with two AutoCompleteTextViews.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".TruitonAutoCompleteTextViewActivity" >

    <AutoCompleteTextView
        android:id="@+id/autoCompleteTextView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:ems="10"
        android:hint="Select Country">
        <requestFocus />
    </AutoCompleteTextView>

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:src="@drawable/truiton" />

    <AutoCompleteTextView
        android:id="@+id/autoCompleteTextView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/autoCompleteTextView1"
        android:layout_below="@+id/autoCompleteTextView1"
        android:ems="10"
        android:hint="Select City" />

</RelativeLayout>

The layout should look something like this:

Now that we have our layout ready the question arises, How to verify if a user has selected a suggested value or entered a new one? Ans is Android AutoCompleteTextView SetOnFocusChangeListener. Our objective here is to create a validation which checks whether the entered value is in the suggestion list or not. If its not in our list, our validation would notify user and would keep restricting user from entering anything other than those values of Android AutoCompleteTextView suggestion list. Now lets have a look at the class TruitonAutoCompleteTextViewActivity where the whole action is happening:

package com.truiton.autocompletetextview;

import java.util.HashMap;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;

public class TruitonAutoCompleteTextViewActivity extends Activity {
 HashMap<String, String> CountryData;
 HashMap<String, String> CityData;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_truiton_auto_complete_text_view);
 CountryData = new HashMap<String, String>();
 CountryData.put("India", "IN");
 CountryData.put("United States", "US");
 CountryData.put("United Kingdom", "GB");
 CountryData.put("Italy", "IT");

 CityData = new HashMap<String, String>();
 CityData.put("City 1", "1");
 CityData.put("City 2", "2");
 CityData.put("City 3", "3");
 CityData.put("City 4", "4");

 setCountries(CountryData.keySet().toArray(new String[0]));
 }

 private void setCountries(String cData[]) {
 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
 android.R.layout.simple_dropdown_item_1line, cData);
 final AutoCompleteTextView countryTextView = (AutoCompleteTextView) 
 findViewById(R.id.autoCompleteTextView1);
 countryTextView.setThreshold(2);
 countryTextView.setAdapter(adapter);
 countryTextView
 .setOnFocusChangeListener(new View.OnFocusChangeListener() {
 @Override
 public void onFocusChange(View view, boolean hasFocus) {
 if (!hasFocus) {
 String val = countryTextView.getText() + "";
 String code = CountryData.get(val);
 Log.v("TruitonAutoCompleteTextViewActivity",
 "Selected Country Code: " + code);
 if (code != null) {
 setCities(CityData.keySet().toArray(
 new String[0]));
 } else {
 countryTextView.setError("Invalid Country");
 }
 }
 }
 });
 }

 private void setCities(String cData[]) {
 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
 android.R.layout.simple_dropdown_item_1line, cData);
 final AutoCompleteTextView cityTextView = (AutoCompleteTextView) 
 findViewById(R.id.autoCompleteTextView2);
 cityTextView.setThreshold(2);
 cityTextView.setAdapter(adapter);
 cityTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
 @Override
 public void onFocusChange(View view, boolean hasFocus) {
 if (!hasFocus) {
 String val = cityTextView.getText() + "";
 String code = CityData.get(val);
 Log.v("TruitonAutoCompleteTextViewActivity",
 "Selected City Code: " + code);
 if (code == null) {
 cityTextView.setError("Invalid City");
 }
 }
 }
 });
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
 // Inflate the menu; this adds items to the action bar if it is present.
 getMenuInflater().inflate(R.menu.truiton_auto_complete_text_view, menu);
 return true;
 }

}

The logic applied in Android AutoCompleteTextView SetOnFocusChangeListener example is simple, all our values for country names are stored in CountryData HashMap. When user starts typing in Android AutoCompleteTextView suggestions appear like this:

Android AutoCompleteTextView SetOnFocusChangeListener Example
Android AutoCompleteTextView

Now if focus is lost from AutoCompleteTextView then our OnFocusChangeListener comes into force unlike TextWatcher or addTextChangedListener which is always in force whenever we type a letter. Android AutoCompleteTextView validation is best implemented by SetOnFocusChangeListener. As the advantage of OnFocusChangeListener is that it runs when focus is changed, thus removing overhead processing. AutoCompleteTextView validation is shown like this :

Android AutoCompleteTextView SetOnFocusChangeListener
Android AutoCompleteTextView Validation

Now if we tap back on the first Android AutoCompleteTextView then the validation error message would be shown:

Android AutoCompleteTextView SetOnFocusChangeListener
Android AutoCompleteTextView Validation Error Message

Now if we start typing again in Android AutoCompleteTextView and select the appropriate suggestion from the list as shown below the validation error message would be gone.

Android AutoCompleteTextView SetOnFocusChangeListener
Android AutoCompleteTextView SetOnFocusChangeListener

I hope this tutorial clears out how to force select item from list in case of Android AutoCompleteTextView. Also this tutorial clears out why Android AutoCompleteTextView SetOnFocusChangeListener approach is better than afterTextChanged() beforeTextChanged() onTextChanged() approach. If you found this tutorial interesting please like, +1, and share on Google+ and Facebook.

About Mohit Gupt

An android enthusiast, and an iPhone user with a keen interest in development of innovative applications.


Leave a comment

Your email address will not be published. Required fields are marked *

5 thoughts on “Android AutoCompleteTextView SetOnFocusChangeListener Example