Dynamiczne aktualizowanie adaptera AutoCompleteTextView

Chcę okresowo zmieniać sugestie podane przez AutoCompleteTextview, pobierając listę z usługi sieciowej RESTful i nie mogę jej sprawnie uruchomić. Skonfigurowałem mocno zakodowaną listę sugestii, aby upewnić się, że działa:

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, new String[] {"Hi", "Ho"});
speciesName.setAdapter(adapter);//my autocomplete tv

Mam Texttwatcher na textview i kiedy Tekst się zmieni, który uruchamia nieblokujące połączenie, aby uzyskać nową listę sugestii -- ta część, która dostaje nową listę działa dobrze. Następnie chcę zresetować adapter, jak więc:

public void setOptionsAndUpdate(String[] options) {
    Log.d(TAG, "setting options");
    //speciesName.setAdapter((ArrayAdapter<String>)null);
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, options);
    speciesName.setAdapter(adapter);
}

Ta metoda jest wywoływana, ale nie działa - lista sugestii albo znika, albo wyświetlane sugestie pozostają niezmienione pomimo wywołania do setAdapter.

Czy to w ogóle właściwe podejście? Spojrzałem na SimpleCursorAdapter, ale nie mogłem zobaczyć, jak zarejestrować moją usługę internetową jako dostawcę treści. (Jest w formie http://www.blah.com/query?term=XX, gdzie XX To wejście z mojej aplikacji, a odpowiedź to tablica łańcuchów JSON.)
Author: Jonik, 2011-11-11

5 answers

W ten sposób aktualizuję mój AutoCompleteTextView:

String[] data = terms.toArray(new String[terms.size()]);  // terms is a List<String>
ArrayAdapter<?> adapter = new ArrayAdapter<Object>(activity, android.R.layout.simple_dropdown_item_1line, data);
keywordField.setAdapter(adapter);  // keywordField is a AutoCompleteTextView
if(terms.size() < 40) keywordField.setThreshold(1); 
else keywordField.setThreshold(2);

Teraz oczywiście jest to statyczne i nie zajmuje się sugestiami over-the-air, ale mogę również zasugerować, aby powiadomić adapter o zmianach po przypisaniu go do AutoCompleteTextView:

adapter.notifyDataSetChanged();   
Mam nadzieję, że to pomoże.

-serkan

 16
Author: serkanozel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-15 20:49:52

Nie miałem szczęścia używać adaptera.notifyDataSetChanged () podczas dynamicznego dodawania i zmiany danych w adapterze. W mojej sytuacji Uderzyłem asynchronicznie w zewnętrzne api i okresowo otrzymywałem listę danych zakończenia.

Ten kod czyści adapter i dodaje nowe dane zgodnie z oczekiwaniami. Jednak musiałem wywołać getFilter ().Metoda filtrowania wymusza wyświetlanie danych. Ponadto musiałem wyraźnie filtrować na podstawie bieżącego tekstu w AutocompleteTextView ponieważ moje wywołanie api było asynchroniczne.

adapter.clear();
for (Map<String, String> map : completions) {
     adapter.add(map.get("name"));
}

//Force the adapter to filter itself, necessary to show new data.
//Filter based on the current text because api call is asynchronous. 
adapter.getFilter().filter(autocompleteTextView.getText(), null);
 32
Author: GLee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-29 19:32:58

Był całkiem dobry samouczek na ten temat, używając zdalnych danych w API Map Google, aby wypełnić AutoCompleteTextView tutaj .

Jeśli potrzebujesz buforowanej wersji, pobrałem ją z Tutaj . Oryginalny samouczek został usunięty, ale zasadniczo musisz napisać ArrayAdapter z niestandardowym filtrem w podobny sposób do pokazanego poniżej i przypisać go do AutoCompleteTextView.

Uwaga: musisz zaimplementować metodę autocomplete (), która zrobi wszystko operacja jest wymagana do synchronicznie pobierania i zwracania elementów autocompletion. Ponieważ filtr jest wywoływany w wątku tła, nie spowoduje to zablokowania głównego wątku interfejsu użytkownika.

private class PlacesAutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
private ArrayList<String> resultList;

public PlacesAutoCompleteAdapter(Context context, int textViewResourceId) {
    super(context, textViewResourceId);
}

@Override
public int getCount() {
    return resultList.size();
}

@Override
public String getItem(int index) {
    return resultList.get(index);
}

@Override
public Filter getFilter() {
    Filter filter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults filterResults = new FilterResults();
            if (constraint != null) {
                // Retrieve the autocomplete results.
                resultList = autocomplete(constraint.toString());

                // Assign the data to the FilterResults
                filterResults.values = resultList;
                filterResults.count = resultList.size();
            }
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            if (results != null && results.count > 0) {
                notifyDataSetChanged();
            }
            else {
                notifyDataSetInvalidated();
            }
        }};
    return filter;
}
}
 22
Author: manyobject,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-25 17:04:58

Ponieważ nie jestem w stanie dodać komentarza, daję nową odpowiedź Nie ma potrzeby czyszczenia adaptera ani wywoływania adaptera.getFilter ().filtr(...)... Aby dynamicznie aktualizować Adapter AutoCompleteTextView, po prostu dodaj nową pozycję do adaptera i ponownie ustawadapter. Dla przykładu podanego w oryginalnym pytaniu, próbowałem następujących i działa (poniższy kod nie pokazuje początkowego ustawienia adaptera, ponieważ wiele odpowiedzi tutaj obejmuje to. To tylko pokazuje aktualizację adapter dynamicznie). Aktualizacja adaptera może być obok kodu aktualizującego listę powiązaną z ArrayAdapter.

    adapter.add(String newSuggestion); // this goes inside a loop for adding multiple suggestions
    speciesName.setAdapter(adapter) ; // speciesName is an AutoCompleteTextView as given in the original question.
 2
Author: sri_s,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-30 07:33:51

Najlepsze rozwiązanie, jakie znalazłem przy aktualizacji adaptera:

Editable text = autocomplete.getText();
autocomplete.setText(text);
autocomplete.setSelection(text.length());

Jak to działa:

Ustawiamy tekst autoCompleteTextView z bieżącym tekstem, więc adapter powiadamia o zmianie danych i aktualizuje zawartość ListView.

Ale za pomocą tej sztuczki kursor przesuwa się na początek edittext. więc używamy autocomplete.setSelection(text.length()) do przesuwania kursora na koniec.

Działa jak urok!

Edit:

Również należy użyć clear(), add() i remove() metody bezpośrednio na twoim ArrayAdapter zamiast Twojego ArrayList.

 0
Author: Nobody8,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-12 11:51:10