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:
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 :
Now if we tap back on the first Android AutoCompleteTextView then the validation error message would be shown:
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.
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.
Born in New Delhi, India. A software engineer by profession, an android enthusiast and an evangelist. My motive here is to create a group of skilled developers, who can develop something new and good. Reason being programming is my passion, and also it feels good to make a device do something you want. In a very short span of time professionally I have worked with many tech firms. As of now too, I am employed as a senior engineer in a leading tech company. In total I may have worked on more than 20 projects professionally, and whenever I get spare time I share my thoughts here at Truiton.
I am in fact grateful to the holder of this web
page who has shared this wonderful article at here.
I am thankful to this writer. thanks a lot to this author for writing woderful Article
Kewl Bro… Good post… 🙂
Thanks bro 🙂
Great article, Mohit 🙂
Everything is clear and short