web-dev-qa-db-ja.com

AutoCompleteTextViewアダプターの動的更新

リストをRESTful Webサービスから取得することにより、AutoCompleteTextviewによって提供される提案を定期的に変更したいのですが、スムーズに機能しません。私はそれが機能することを確認するために提案のハードコードされたリストを設定しました:

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

TextViewにTextWatcherがあり、テキストが変更されて非提案呼び出しが起動され、新しい提案のリストが取得された場合、新しいリストを取得するこの部分は正常に機能しています。次に、次のようにアダプターをリセットします。

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);
}

このメソッドは呼び出されますが、機能しません-setAdapterの呼び出しにもかかわらず、提案のリストが消えるか、表示された提案は変更されないままです。

これは正しいアプローチですか? SimpleCursorAdapterを見ましたが、Webサービスをコンテンツプロバイダーとして登録する方法がわかりませんでした。 (形式は http://www.blah.com/query?term=XX です。XXはアプリからの入力であり、応答は文字列のJSON配列です。)

36
jaybee

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);

もちろん、これは静的であり、無線による提案を処理しませんが、AutoCompleteTextViewに割り当てた後、アダプターに変更を通知することもお勧めします。

adapter.notifyDataSetChanged();   

お役に立てれば。

-セルカン

18
serkanozel

アダプターのデータを動的に追加および変更するときにadapter.notifyDataSetChanged()を使用することはできませんでした。私の状況では、外部APIに非同期でアクセスし、定期的に完了データのリストを取得していました。

このコードはアダプターをクリアし、期待どおりに新しいデータを追加します。ただし、データを強制的に表示するにはgetFilter()。Filterメソッドを呼び出す必要がありました。また、API呼び出しは非同期であったため、AutocompleteTextViewの現在のテキストに基づいて明示的にフィルター処理する必要がありました。

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);
41
GLee

このトピックには、Google Map APIのリモートデータを使用してAutoCompleteTextView here を設定する非常に優れたチュートリアルがありました。

キャッシュバージョンが必要な場合は、 here から取得しました。元のチュートリアルは削除されましたが、基本的に、以下に示す方法と同様の方法でカスタムフィルターを使用してArrayAdapterを作成し、AutoCompleteTextViewに割り当てる必要があります。

注:オートコンプリートアイテムを同期的に取得して返すために必要な操作を行うautocomplete()メソッドを実装する必要があります。フィルタはバックグラウンドスレッドで呼び出されるため、メインUIスレッドはブロックされません。

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;
}
}
23
user937783

コメントを追加できないため、新しい回答をしていますアダプタをクリアしたり、adapter.getFilter()。filter(...)を呼び出す必要はありません... AutoCompleteTextViewアダプタを動的に更新するには、単に追加しますアダプターに新しいアイテムを追加し、setAdapterを再度作成します。元の質問で与えられた例について、私は次を試してみましたが、うまくいきます(ここの複数の答えがそれをカバーしているため、以下のコードはアダプターの初期設定を示していません。これはアダプターを動的に更新することを示しています)。アダプタの更新は、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
sri_s

アダプタを更新するために見つけた最良の解決策:

_Editable text = autocomplete.getText();
autocomplete.setText(text);
autocomplete.setSelection(text.length());
_

仕組み:

autoCompleteTextViewのテキストを現在のテキストに設定し、アダプターがデータが変更されたことを通知し、listViewsのコンテンツを更新します。

しかし、このトリックにより、カーソルは編集テキストの先頭に移動します。そのため、カーソルを最後に移動するためにautocomplete.setSelection(text.length())を使用します。

チャームのように動作します!

編集:

また、ArrayAdapterの代わりにArrayListで直接clear()add()、およびremove()メソッドを使用する必要があります。

2
Nobody8