12

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.

Cœur
  • 32,421
  • 21
  • 173
  • 232
kaushal trivedi
  • 3,217
  • 1
  • 26
  • 44

2 Answers2

19

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));
pskink
  • 21,078
  • 6
  • 53
  • 68
  • 1
    Hey, I got the solution,you was right about your comment.it helped me to partially solve the issue. Though i had some other issues too that i am currently working on. I didn't check this way to achieve the answer as i don't want to use database for this single purpose. I am thankful to you for your complete support and giving you upcount for this one. thanks for all your help. – kaushal trivedi Nov 14 '13 at 12:02
  • i dont use any database, data is read from the json web service – pskink Nov 14 '13 at 12:28
  • I tried so many different things so far: TextWatcher, AsyncTask, etc. This is exactly was I was looking for ! Best piece of code I could find. Works perfectly ! – Olivier Picault Dec 31 '16 at 14:00
  • 1
    @OlivierP. simple yet working, isn't it? unfortunately 90% of people here still want to fight with those watchers, custom ArrayAdapters, AsyncTasks etc even if they saw this so simple solution, i have no idea why... – pskink Dec 31 '16 at 14:25
  • @pskink I was one of them ^^ I din't know this could be done this way. I'm glad I found your piece of code. Moreover when you search over Internet, StackOverflow, etc. your answer is not the highlighted one where it should definitely be ! – Olivier Picault Dec 31 '16 at 14:45
  • @OlivierP. you were one of them but you didnt see this solution before, i am talking about those guys who saw it but still believe that data stored in some POJO and `ArrayAdapter` is somehow "better" than data stored in a `Cursor` used by a `CursorAdapter` – pskink Dec 31 '16 at 14:51
0

You have impletent the custome filter in the child class of ArrayAdapter, there in perform filter method you have to do network call and get data from server. You can set this data in your main arraylist.

Shailendra Yadav
  • 1,612
  • 1
  • 9
  • 13