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.

21 comments:

  1. That is very helpful code! Your blog is very very great! I love it!

    ReplyDelete
  2. Thanks for the help. this is great

    ReplyDelete
  3. I need to use the value selected from the AutoCompleteTextBox in a string, i tried using..

    textView = (AutoCompleteTextView) findViewById(R.id.stock);
    ArrayAdapter adapter = new ArrayAdapter(this,
    android.R.layout.simple_dropdown_item_1line,stocks_array);
    textView.setAdapter(adapter);


    String str = textView.getText().toString();


    but i get an empty string everytime?

    Thanks in advance..
    Bhuvan

    ReplyDelete
  4. Hi Bhuvan ,
    setOnItemClickListener for your textView (AutoCompleteTextView).Then inside this setOnItemClickListener block you can get selected item string as follows:

    String mSearchResult = arg0.getItemAtPosition(arg2).toString() ;


    Regards
    Murthy

    ReplyDelete
  5. This is a nice description.

    I have to do something extra work that:
    after geting the string from AutoCompleteTextView
    i have to use that string to match with oter URL.

    so I am using setOnItemSelectedListener() , but it works on selection of the string. what to do ?

    ReplyDelete
  6. Hi....i am writing an app that will store the user email in an sqlite database. How can i link it to the edittext view so that once stored, on subsequent logins it has an autocomplete functionality?

    ReplyDelete
  7. Hi...how can i link the values for the autocomplete view to an sqlite database?

    ReplyDelete
  8. Well, For your case, 2 ways:

    1. Everytime you show the login page, query the DB and prepare the adapter with results.

    2. Use a CursorAdapter which queries your table.

    ReplyDelete
  9. use MultiAutoselectTextview....dont need to build one when there is one already there :)

    ReplyDelete
  10. Thanks Anonymous. I will update the post to point to that widget. My objective was to show how to customize the AutoComplete widget. For this example, of course you can use the MultiAutoCompleteTextView. This example was to show how to override and implement the AutoCompleteTextView in whatever way you like.

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete
  12. Can you help me modify the result, for example I got result when selected an item is "{Name=Somebody, No=12345};"
    But the thing I want is "Somebody<12345>;". How can we do that?

    ReplyDelete
    Replies
    1. Hi
      I have the same question. Did you find solution to your question?
      Please help me out.

      Thanks
      Tanka nath Sharma

      Delete
    2. Hi
      I am having the same problem. Can you please tell me how did you solve your question.

      Thanks
      Tanka Nath Sharma

      Delete
  13. Great tutorial, but please help me. In my SMS app I have a clear button, so when I click on it, the app gets force closes when I try to set the auto complete text view text to blank i.e to.setTet(""); Please help, how can I clear the auto complete text box.

    ReplyDelete
  14. How to get string text from autocompletetextview

    ReplyDelete
  15. Hi,
    How can i use MultiAutocompleteTextView to show 2 lines of text, similar to Android's default messaging application. I want to make similar application. First line to show name and second line to show number.

    ReplyDelete
  16. i want to use substr() in sqlite database to retrive record save in in particular months and years and also last week .
    can you help me in this topic

    ReplyDelete
  17. Can we remove/customize divider any how?

    ReplyDelete
  18. Bhuvan

    you can do like that...............

    textView = (AutoCompleteTextView) findViewById(R.id.stock);
    ArrayAdapter adapter = new ArrayAdapter(this,
    android.R.layout.simple_dropdown_item_1line,stocks_array);
    textView.setAdapter(adapter);



    textView.addTextChangedListener(new TextWatcher()
    {
    public void afterTextChanged(Editable s)
    {
    }
    public void beforeTextChanged(CharSequence s, int start, int count, int after)
    {
    }
    public void onTextChanged(CharSequence s, int start, int before, int count)
    {
    String str=s.toString();

    ReplyDelete
  19. How to remove or change the DIVIDER in a AutoCompleteTextView?

    ReplyDelete