【问题标题】:Android - ActionBar SearchView suggestions with a simple String arrayAndroid - 带有简单字符串数组的 ActionBar SearchView 建议
【发布时间】:2014-07-02 17:45:00
【问题描述】:

我想实现一个具有建议功能的 ActionBar 搜索小部件。
我已经在我的 ORMLite 数据库中存储了一个字符串数组,我想将其用于建议。
如何在不创建大量类(Provider、Searchable...!)的情况下做到这一点?

【问题讨论】:

  • 创建您的自定义 CursorAdapter 使用 MatrixCursor 填充它,并将适配器设置为 SearchView developer.android.com/reference/android/support/v7/widget/…,让我知道这些信息是否足够。
  • 在文档中说有一个像 CursorAdapter(Context context, Cursor cursor) 这样的构造函数。我尝试使用矩阵作为我创建的 MatrixCursor 来做到这一点new CursorAdapter(this, matrix)。但是实例化一个 CursorAdapter 是不可能的……?

标签: android android-actionbar ormlite searchview


【解决方案1】:

这是一个示例,希望对您有所帮助。

在此游标中实现更多功能,例如。按下建议项时打开活动,看看这个http://developer.android.com/guide/topics/search/adding-custom-suggestions.html

 package com.roberto.android.thetracker.app;

 import android.database.MatrixCursor;
 import android.os.Bundle;
 import android.provider.BaseColumns;
 import android.support.v4.app.Fragment;
 import android.support.v4.view.MenuItemCompat;
 import android.support.v4.widget.CursorAdapter;
 import android.support.v4.widget.SimpleCursorAdapter;
 import android.support.v7.widget.SearchView;
 import android.view.Menu;
 import android.view.MenuInflater;

 public class CustomSearchFragment extends Fragment {

     private static final String[] SUGGESTIONS = {
             "Bauru", "Sao Paulo", "Rio de Janeiro",
             "Bahia", "Mato Grosso", "Minas Gerais",
             "Tocantins", "Rio Grande do Sul"
     };
     private SimpleCursorAdapter mAdapter;

     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);

         final String[] from = new String[] {"cityName"};
         final int[] to = new int[] {android.R.id.text1};
         mAdapter = new SimpleCursorAdapter(getActivity(),
                 android.R.layout.simple_list_item_1,
                 null,
                 from,
                 to,
                 CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
     }

     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         setHasOptionsMenu(true);
     }

     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         super.onCreateOptionsMenu(menu, inflater);
         inflater.inflate(R.menu.main, menu);
     }

     @Override
     public void onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
         final SearchView searchView = (SearchView) MenuItemCompat
                 .getActionView(menu.findItem(R.id.action_search));
         searchView.setSuggestionsAdapter(mAdapter);
         searchView.setIconifiedByDefault(false);

         // Getting selected (clicked) item suggestion
         searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
             @Override
             public boolean onSuggestionClick(int position) {
                 Cursor cursor = (Cursor) mAdapter.getItem(position);
                 String txt = cursor.getString(cursor.getColumnIndex("cityName"));
                 searchView.setQuery(txt, true);
                 return true;
             }

             @Override
             public boolean onSuggestionSelect(int position) {
                 // Your code here
                 return true;
             }
         });

         searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
             @Override
             public boolean onQueryTextSubmit(String s) {
                 return false;
             }

             @Override
             public boolean onQueryTextChange(String s) {
                 populateAdapter(s);
                 return false;
             }
         });
     }

     // You must implements your logic to get data using OrmLite
     private void populateAdapter(String query) {
         final MatrixCursor c = new MatrixCursor(new String[]{ BaseColumns._ID, "cityName" });
         for (int i=0; i<SUGGESTIONS.length; i++) {
             if (SUGGESTIONS[i].toLowerCase().startsWith(query.toLowerCase()))
                 c.addRow(new Object[] {i, SUGGESTIONS[i]});
         }
         mAdapter.changeCursor(c);
     }

 }

【讨论】:

  • 我正确地实现了你的代码,我从我的 ORMLite 数据库中得到了历史数组,它全部编译没有错误。除了当我在数据库中输入一个作为字符串开头的字符时,什么都没有发生,当我输入第二个字符时,我得到ArrayIndexOutOfBoundsException...我不知道为什么...
  • 这里:snipt.org/VCy7#expand 我将 String 数组转换为 ArrayList,以便稍后添加。
  • 谢谢,非常有用的例子。拯救了我的一天@betorcs
  • @hitesh-sarsava,from 是游标列名称,to 是视图 ID
  • @betorcs 最后我发现了问题,自动完成文本视图的默认阈值为 2 个字符,这就是为什么它不适用于单个字符。我必须这样做 ((AutoCompleteTextView) searchView.findViewById(R.id.search_src_text)).setThreshold(1);更改默认阈值。
【解决方案2】:
 private String getSuggestion(int position) {
        MatrixCursor cursor = (MatrixCursor) searchView.getSuggestionsAdapter().getCursor();
        String suggest1 = cursor.getString(position);


        return SUGGESTIONS[Integer.valueOf(suggest1)];
    }

【讨论】:

  • 虽然此代码可能会回答问题,但您仍然可以考虑添加一些解释性句子,因为这会增加您的答案对其他用户的价值。
【解决方案3】:

基于betorcs的回答

你不需要

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {...});

你可以用这个代替那个

mAdapter.setFilterQueryProvider(new FilterQueryProvider() {
    @Override
    public Cursor runQuery(CharSequence constraint) {
        return populateAdapter((String) constraint);
    }
});

在 populateAdapter 上,替换“return c;”用“mAdapter.changeCursor(c);”

private Cursor populateAdapter(String query) {
    .
    .
    .
    return c;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 2013-03-03
    • 2013-04-06
    • 1970-01-01
    • 2013-12-04
    • 1970-01-01
    相关资源
    最近更新 更多