Sunday, April 4, 2010

Custom AutoComplete for Android

The default custom AutoCompleteTextView is quite a nice widget. But if you want to extend it's functionality, you will need to write your own custom widget. As an example, if you wish to have a EditText for a "To" address field as any email application has, where you want to collect multiple selections from the list that pops up, you will need to extend the AutoCompleteTextView class and write your own small little widget. It's very simple to create one that will suit your need.
So here we go.
1. Class CustomAutoComplete.java
   1: package com.beanie.example.widgets;
   2: import android.content.Context;
   3: import android.text.TextUtils;
   4: import android.util.AttributeSet;
   5: import android.widget.AutoCompleteTextView;
   6:  
   7: public class CustomAutoComplete extends AutoCompleteTextView {
   8:     private String previous = "";
   9:     private String seperator = ";";
  10:     public CustomAutoComplete(final Context context, final AttributeSet attrs, final int defStyle) {
  11:         super(context, attrs, defStyle);
  12:         this.setThreshold(0);
  13:     }
  14:     public CustomAutoComplete(final Context context, final AttributeSet attrs) {
  15:         super(context, attrs);
  16:         this.setThreshold(0);
  17:     }
  18:     public CustomAutoComplete(final Context context) {
  19:         super(context);
  20:         this.setThreshold(0);
  21:     }
  22:     /**
  23:      * This method filters out the existing text till the separator
  24:      * and launched the filtering process again
  25:      */
  26:     @Override
  27:     protected void performFiltering(final CharSequence text, final int keyCode) {
  28:         String filterText = text.toString().trim();
  29:         previous = filterText.substring(0,filterText.lastIndexOf(getSeperator())+1);
  30:         filterText = filterText.substring(filterText.lastIndexOf(getSeperator()) + 1);
  31:         if(!TextUtils.isEmpty(filterText)){
  32:             super.performFiltering(filterText, keyCode);
  33:         }
  34:     }
  35:     /**
  36:      * After a selection, capture the new value and append to the existing
  37:      * text
  38:      */
  39:     @Override
  40:     protected void replaceText(final CharSequence text) {
  41:         super.replaceText(previous+text+getSeperator());
  42:     }
  43:     public String getSeperator() {
  44:         return seperator;
  45:     }
  46:     public void setSeperator(final String seperator) {
  47:         this.seperator = seperator;
  48:     }
  49: }
This class is the main widget class that extends thet AutoCompleteTextView. You have to override 2 methods,
protected void replaceText(final CharSequence text)
protected void performFiltering(final CharSequence text, final int keyCode)
2. You main layout file (main.xml)
   1: <?xml version="1.0" encoding="utf-8"?>
   2: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   3:     android:orientation="vertical" android:layout_width="fill_parent"
   4:     android:layout_height="fill_parent">
   5:     <com.beanie.example.widgets.CustomAutoComplete android:layout_width="fill_parent"
   6:         android:layout_height="wrap_content" android:id="@+id/autocomplete"/>
   7: </LinearLayout>
3. Now we test it. This is your activity class.
   1: package com.beanie.example;
   2: import android.app.Activity;
   3: import android.os.Bundle;
   4: import android.widget.ArrayAdapter;
   5: import com.beanie.example.widgets.CustomAutoComplete;
   6:  
   7: public class TestAutoComplete extends Activity {
   8:     /** Called when the activity is first created. */
   9:     @Override
  10:     public void onCreate(Bundle savedInstanceState) {
  11:         super.onCreate(savedInstanceState);
  12:         setContentView(R.layout.main);
  13:         CustomAutoComplete myAutoComplete = (CustomAutoComplete)findViewById(R.id.autocomplete);
  14:         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line);
  15:  
  16:         adapter.add("aaaa");
  17:         adapter.add("abaa");
  18:         adapter.add("acaa");
  19:         adapter.add("adaa");
  20:         adapter.add("aaba");
  21:         adapter.add("aaca");
  22:         adapter.add("aaba");
  23:         adapter.add("aaae");
  24:         
  25:         myAutoComplete.setAdapter(adapter);
  26:     }
  27: }
1Voila, you are done. Here’s a screenshot of our Custom Auto-Complete Text view at work.

You can also change the separator from the default “;” to any other character like a “,” or anything else.
On the adapter, you call the method setSeparator(String any);
Now you have your own custom auto-complete widget for Android.

For this particular example, however, Android provides you a widget by default. MultiAutoCompleteTextView is specifically designed to handle such kind of input.