How to dynamically add suggestions to autocompletetextview with preserving character status

kaushal trivedi picture kaushal trivedi · Nov 8, 2013 · Viewed 9.7k times · Source

Problem Description:

I am facing some problem with AutoCompleteTextView where I have to show suggestions after each keypress. Thing is that, list of suggestion is dynamic like google's suggestion feature. It means the new suggestions should be added as user keeps typing in plus all matching old suggestions should be displayed.

For example

I write "te" and then it should display previous suggestions like "test1" & "test2" and the new suggestions that I will get from Web API. Suppose web api gives me word "tea"& "tension ".

Now the AutoCompleteTextView will have "te" as string with all four suggestions showing below it.

This is exactly what I am looking for.

looks simple but it is showing a strange behaviour.

I am using default ArrayAdapter class instance of which I am declaring globally.

arrayAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line,suggestions);
word.setAdapter(arrayAdapter);

suggestions is ArrayList.

Upon getting new result from WebApi I simply call

arrayAdapter.notifyDataSetChanged();

to refresh the data observer and views attached with this (in our case AutoCompleteListView).

But it closes suggestions.

When I don't use notifyDataSetChanged(); it is showing all suggestions regardless of characters I have typed.

I tried it with custom filter as many suggested but none of them is helpful as I couldn't use notifyDataSetChanged().

I am posting an image to avoid confusions.enter image description here

I have a confusion that why notifyDataSetChanged(); its not working. I haven't use any other reference of list with same arrayAdapter instance. I really doubt if it's a reference problem.

Answer

pskink picture pskink · Nov 8, 2013

one of the easiest way of doing that (put the code in onCreate):

EDIT: addied wikipedia free opensearch (if https://en.wikipedia.org doesn't work try http://en.wikipedia.org)

    AutoCompleteTextView actv = new AutoCompleteTextView(this);
    actv.setThreshold(1);
    String[] from = { "name", "description" };
    int[] to = { android.R.id.text1, android.R.id.text2 };
    SimpleCursorAdapter a = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, null, from, to, 0);
    a.setStringConversionColumn(1);
    FilterQueryProvider provider = new FilterQueryProvider() {
        @Override
        public Cursor runQuery(CharSequence constraint) {
            // run in the background thread
            Log.d(TAG, "runQuery constraint: " + constraint);
            if (constraint == null) {
                return null;
            }
            String[] columnNames = { BaseColumns._ID, "name", "description" };
            MatrixCursor c = new MatrixCursor(columnNames);
            try {
                String urlString = "https://en.wikipedia.org/w/api.php?" +
                        "action=opensearch&search=" + constraint +
                        "&limit=8&namespace=0&format=json";
                URL url = new URL(urlString);
                InputStream stream = url.openStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
                String jsonStr = reader.readLine();
                // output ["query", ["n0", "n1", ..], ["d0", "d1", ..]]
                JSONArray json = new JSONArray(jsonStr);
                JSONArray names = json.getJSONArray(1);
                JSONArray descriptions = json.getJSONArray(2);
                for (int i = 0; i < names.length(); i++) {
                    c.newRow().add(i).add(names.getString(i)).add(descriptions.getString(i));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return c;
        }
    };
    a.setFilterQueryProvider(provider);
    actv.setAdapter(a);
    setContentView(actv, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));