将ArrayAdapter转换为CursorAdapter以在SearchView中使用

22

我该如何将静态数据的 ArrayAdapter<String> 转换为 CursorAdapter ,以便在 SearchView 中使用建议监听器?我已经从静态数据 (allString) 构建了 ArrayAdapter<String>

ArrayAdapter<String> searchAdapter = new ArrayAdapter<String>(context, R.layout.listitem, allString);

我在一个MultiAutoCompleteTextView中使用它,在API级别低于11的设备上运行正常。

MultiAutoCompleteTextView findTextView.setAdapter(searchAdapter);
然而,我的目标API级别是11,对于API>10的情况下我使用一个ActionBar,其中我想要有一个SearchView。这是我尝试过的:它显示了嵌入的SearchViewActionBar,但不像MultiAutoCompleteTextView那样给出任何建议。
@Override
public boolean onCreateOptionsMenu(Menu menu) {     
        MenuInflater inflater = getMenuInflater();

         if (android.os.Build.VERSION.SDK_INT > 10){
             inflater.inflate(R.menu.menu11, menu);
             searchView = (SearchView) menu.findItem(R.id.MENU_SEARCH).getActionView();
             int[] to = {0};
             CursorAdapter cursorAdapter = new SimpleCursorAdapter(context, R.layout.listitem, null, allBusStopString, to);
             searchView.setSuggestionsAdapter(cursorAdapter);
             searchView.setOnSuggestionListener(new OnSuggestionListener() {

                @Override
                public boolean onSuggestionClick(int position) {
                    String selectedItem = (String)cursorAdapter.getItem(position);
                    Log.v("search view", selectedItem);
                    return false;
                }

                @Override
                public boolean onSuggestionSelect(int position) {
                    return false;
                }
             });  
         }else{
             inflater.inflate(R.menu.menu, menu);
         }

    return true;
}
2个回答

30

很奇怪SearchView.setSuggestionsAdapter仅接受CursorAdapter。

您可以创建MatrixCursor并使用字符串数组中的数据填充它。我希望您的数据集很小。

然后将游标传递给CursorAdapter。

String[] columnNames = {"_id","text"}
MatrixCursor cursor = new MatrixCursor(columnNames);
String[] array = getResources().getStringArray(R.array.allStrings); //if strings are in resources
String[] temp = new String[2];
int id = 0;
for(String item : array){
    temp[0] = Integer.toString(id++);
        temp[1] = item;
    cursor.addRow(temp);
}               
String[] from = {"text"}; 
int[] to = {R.id.name_entry};
busStopCursorAdapter = new SimpleCursorAdapter(context, R.layout.listentry, cursor, from, to);

1
我只需要添加_id列以避免在此处解释的错误。 - Behzad Momahed Heravi
2
我认为你需要设置 OnQueryTextListener,在此监听器中重新创建游标并在适配器中更改游标。 - pawelzieba
@BehzadMomahedHeravi:我正在做同样的事情,但不知道如何使用我的自定义内容提供程序来完成它。我想过滤我设备上可用的歌曲。你能帮我吗? - Shreyash Mahajan
太棒了!我得到了我想要的解决方案。 - Shreyash Mahajan
如何在文本更改时过滤结果? - Ravi Theja
显示剩余5条评论

17

我曾经遇到过类似的问题。你可以使用 SearchView.setSuggestionsAdapter() 方法,它只接受 CursorAdapter。但是...这样做有什么意义呢?如果你使用标准的 <android.support.v7.widget.SearchView /> ,那么它包含了 SearchAutoComplete,而 SearchAutoComplete 继承自 AppCompatAutoCompleteTextView。下面的代码对我有用:

List<String> items = Lists.newArrayList(new String[] {"aaaaa", "bbbbb", "ccccc", "ddddd"});
SearchView searchView = (SearchView) findViewById(R.id.autocomplete_searchview);
SearchView.SearchAutoComplete searchSrcTextView = (SearchView.SearchAutoComplete) findViewById(android.support.v7.appcompat.R.id.search_src_text);
searchSrcTextView.setThreshold(1);
searchSrcTextView.setAdapter(new SuggestionAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, items));
searchSrcTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        return;
    }
});

以下是适配器代码:

public class SuggestionAdapter<T> extends ArrayAdapter<T> {

    private List<T> items;
    private List<T> filteredItems;
    private ArrayFilter mFilter;

    public SuggestionAdapter(Context context, @LayoutRes int resource, @NonNull List<T> objects) {
        super(context, resource, Lists.<T>newArrayList());
        this.items = objects;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public T getItem(int position) {
        return items.get(position);
    }

    @Override
    public Filter getFilter() {
        if (mFilter == null) {
            mFilter = new ArrayFilter();
        }
        return mFilter;
    }

    public int getCount() {
        //todo: change to pattern-size
        return items.size();
    }

    private class ArrayFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence prefix) {
            FilterResults results = new FilterResults();

            //custom-filtering of results
            results.values = items;
            results.count = items.size();

            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            filteredItems = (List<T>) results.values;
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }
    }
}

无论您输入什么,这将返回所有内容。 - Mike6679
如果您没有真正的光标,这是最佳解决方案(手动填充光标是一种不好的方法)。现在它对我有用了,但我需要更改一些示例代码:
  • 为searchAutoComplete使用findViewById,例如searchView.findViewById
  • 重写适配器的getItems和getCounts,使用filteredItems而不是items
  • 很明显,您需要实施您自己的筛选逻辑,就像“// custom-filtering of results”注释所说的那样。
非常感谢提供示例代码!
- AliMola
这太完美了,我正在使用一个弹性搜索端点,我只需获取数据并在获得新的搜索结果时重置适配器。 - Aaron Dancygier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接