Android:提供最近的searchbuild议,而无需search活动?

我有一个ActionBar SearchView,我成功地能够使用它进行search。 Android文档没有解释如何实现searchbuild议。 我不想有一个可search的活动。

这是我的search代码:

public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_add_song, menu); final SearchView searchView = (SearchView) menu.findItem(R.id.song_search).getActionView(); searchView.setFocusable(true); searchView.setIconified(false); final AddSongActivity activity = this; searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextChange(String newText) { // Do nothing return true; } @Override public boolean onQueryTextSubmit(String query) { // Clear SearchView searchView.clearFocus(); // Begin Spotify Search TextView notice = (TextView)findViewById(R.id.search_notice); URL url; try { url = new URL("http://ws.spotify.com/search/1/track.json?q=" + URLEncoder.encode(query,"UTF-8")); } catch (MalformedURLException e) { notice.setText("Malformed Search"); notice.setHeight(noticeHeight); return true; } catch (UnsupportedEncodingException e) { notice.setText("Unsupported Encoding. Maybe a problem with your device."); notice.setHeight(noticeHeight); return true; } new SearchDownload(url, activity).execute(); notice.setText("Loading Tracks"); notice.setHeight(noticeHeight); Log.i("infodb","" + noticeHeight); return true; } }); 

这适用于search,但我不知道实施最近的search查询build议。 我怎么去做这个?

谢谢。

Solutions Collecting From Web of "Android:提供最近的searchbuild议,而无需search活动?"

好的,我花了我的时间。 我从SQLiteDatabase做我自己的简单的build议实现。

我们将创build3个类如下

  1. MainActivity – 用于从数据库中检索SearchViewbuild议
  2. SuggestionDatabase – 这将存储您最近的search关键字。
  3. SuggestionSimpleCursorAdapter – 这是SimpleCursorAdapter的子类。 我将解释为什么我让这个类而不是使用SimpleCursorAdapter

代码

 // MainActivity.java public class MainActivity extends Activity implements SearchView.OnQueryTextListener, SearchView.OnSuggestionListener { private SuggestionsDatabase database; private SearchView searchView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); database = new SuggestionsDatabase(this); searchView = (SearchView) findViewById(R.id.searchView1); searchView.setOnQueryTextListener(this); searchView.setOnSuggestionListener(this); } @Override public boolean onSuggestionSelect(int position) { return false; } @Override public boolean onSuggestionClick(int position) { SQLiteCursor cursor = (SQLiteCursor) searchView.getSuggestionsAdapter().getItem(position); int indexColumnSuggestion = cursor.getColumnIndex( SuggestionsDatabase.FIELD_SUGGESTION); searchView.setQuery(cursor.getString(indexColumnSuggestion), false); return true; } @Override public boolean onQueryTextSubmit(String query) { long result = database.insertSuggestion(query); return result != -1; } @Override public boolean onQueryTextChange(String newText) { Cursor cursor = database.getSuggestions(newText); if(cursor.getCount() != 0) { String[] columns = new String[] {SuggestionsDatabase.FIELD_SUGGESTION }; int[] columnTextId = new int[] { android.R.id.text1}; SuggestionSimpleCursorAdapter simple = new SuggestionSimpleCursorAdapter(getBaseContext(), android.R.layout.simple_list_item_1, cursor, columns , columnTextId , 0); searchView.setSuggestionsAdapter(simple); return true; } else { return false; } } } 

怎么运行的

  1. 当用户点击searchbutton, onQueryTextSubmit()将被触发,然后search关键字将被保存在我们的数据库。 假设我们提交关键字“你好”
  2. 如果用户在SearchView写入例如“Hel”或“H”的string, onQueryTextChange()将被调用,然后我们在SQLiteDatabaseSuggestionDatabase )中search这个关键字。 如果“Hel”或“H”匹配“Hello”,则通过在SuggestionSimpleCursorAdapter设置返回的游标显示查询结果,然后在SearchView设置该适配器。 这是图片。

在这里输入图像说明
3.当然我们会点击“Hello”的build议, onSuggestionClick(int position)会被调用。 我们从SearchView的适配器( SuggestionSimpleCursorAdapter )中获取SQLiteCursor对象,并从中获取build议文本,在SearchView对象中设置build议文本

 SQLiteCursor cursor = (SQLiteCursor) searchView.getSuggestionsAdapter().getItem(position); int indexColumnSuggestion = cursor.getColumnIndex( SuggestionsDatabase.FIELD_SUGGESTION); searchView.setQuery(cursor.getString(indexColumnSuggestion), false); 

如果我们使用SimpleCursorAdapter它也可以正常工作,但是假设我们有这种情况

  1. 如果我们在智能手机上运行这个程序,并input关键字“Hel”,build议将正确显示。

在这里输入图像说明

  1. 如果我们在风景中旋转屏幕怎么办? 它将以全屏模式切换,您仍然可以键入关键字。

会有什么build议? 让我们来看看。

在这里输入图像说明

看到奇怪的build议? 我们如何解决? 通过覆盖返回CharSequenceconvertToString(Cursor cursor)

  // SuggestionSimpleCursorAdapter.java public class SuggestionSimpleCursorAdapter extends SimpleCursorAdapter { public SuggestionSimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { super(context, layout, c, from, to); } public SuggestionSimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) { super(context, layout, c, from, to, flags); } @Override public CharSequence convertToString(Cursor cursor) { int indexColumnSuggestion = cursor.getColumnIndex(SuggestionsDatabase.FIELD_SUGGESTION); return cursor.getString(indexColumnSuggestion); } } 

通过覆盖convertToString(Cursor cursor) ,结果如下

在这里输入图像说明

这里是数据库

 // SuggestionDatabase.java public class SuggestionsDatabase { public static final String DB_SUGGESTION = "SUGGESTION_DB"; public final static String TABLE_SUGGESTION = "SUGGESTION_TB"; public final static String FIELD_ID = "_id"; public final static String FIELD_SUGGESTION = "suggestion"; private SQLiteDatabase db; private Helper helper; public SuggestionsDatabase(Context context) { helper = new Helper(context, DB_SUGGESTION, null, 1); db = helper.getWritableDatabase(); } public long insertSuggestion(String text) { ContentValues values = new ContentValues(); values.put(FIELD_SUGGESTION, text); return db.insert(TABLE_SUGGESTION, null, values); } public Cursor getSuggestions(String text) { return db.query(TABLE_SUGGESTION, new String[] {FIELD_ID, FIELD_SUGGESTION}, FIELD_SUGGESTION+" LIKE '"+ text +"%'", null, null, null, null); } private class Helper extends SQLiteOpenHelper { public Helper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE "+TABLE_SUGGESTION+" ("+ FIELD_ID+" integer primary key autoincrement, "+FIELD_SUGGESTION+" text);"); Log.d("SUGGESTION", "DB CREATED"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } } 

我希望这个答案对其他程序员很有用。 🙂

onCreate methodMainActivity类中,首先使用这个代码

 AutoCompleteTextView search_text = (AutoCompleteTextView) searchView.findViewById(searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null)); search_text.setThreshold(1); 

这个setThreshold(1)意味着它现在可以从一个字符search文本。

我的需求更简单 – 我不需要数据库,因为我有许多想要显示在ArrayList中的build议。

这是一个示例实现:

 import java.util.ArrayList; import android.app.Activity; import android.app.SearchManager; import android.content.Context; import android.database.Cursor; import android.database.MatrixCursor; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.CursorAdapter; import android.widget.SearchView; import android.widget.SearchView.OnQueryTextListener; import android.widget.TextView; import android.widget.Toast; public class ActivityTest extends Activity implements OnQueryTextListener { private static final String COLUMN_ID = "_id"; private static final String COLUMN_TERM = "term"; private static final String DEFAULT = "default"; private SearchManager searchManager; private SearchView searchView; private MenuItem searchMenuItem; private SuggestAdapter suggestionsAdapter; private final ArrayList<String> suggestionsArray = new ArrayList<String>(); private final ArrayList<String> dummyArray = new ArrayList<String>(); @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Create some dummy entries dummyArray.add("apples"); dummyArray.add("oranges"); dummyArray.add("bananas"); dummyArray.add("pears"); dummyArray.add("plums"); } @Override public boolean onCreateOptionsMenu(final Menu menu) { getMenuInflater().inflate(R.menu.main, menu); searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); searchMenuItem = menu.findItem(R.id.action_search); searchView = (SearchView) searchMenuItem.getActionView(); searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); searchView.setOnQueryTextListener(this); final MatrixCursor matrixCursor = getCursor(suggestionsArray); suggestionsAdapter = new SuggestAdapter(this, matrixCursor, suggestionsArray); searchView.setSuggestionsAdapter(suggestionsAdapter); suggestionsAdapter.notifyDataSetChanged(); return true; } @Override public boolean onQueryTextChange(final String newText) { suggestionsArray.clear(); for (int i = 0; i < dummyArray.size(); i++) { if (dummyArray.get(i).contains(newText)) { suggestionsArray.add(dummyArray.get(i)); } } final MatrixCursor matrixCursor = getCursor(suggestionsArray); suggestionsAdapter = new SuggestAdapter(this, matrixCursor, suggestionsArray); searchView.setSuggestionsAdapter(suggestionsAdapter); suggestionsAdapter.notifyDataSetChanged(); return true; } @Override public boolean onQueryTextSubmit(final String query) { // TODO Auto-generated method stub return false; } private class SuggestAdapter extends CursorAdapter implements OnClickListener { private final ArrayList<String> mObjects; private final LayoutInflater mInflater; private TextView tvSearchTerm; public SuggestAdapter(final Context ctx, final Cursor cursor, final ArrayList<String> mObjects) { super(ctx, cursor, 0); this.mObjects = mObjects; this.mInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View newView(final Context ctx, final Cursor cursor, final ViewGroup parent) { final View view = mInflater.inflate(R.layout.list_item_search, parent, false); tvSearchTerm = (TextView) view.findViewById(R.id.tvSearchTerm); return view; } @Override public void bindView(final View view, final Context ctx, final Cursor cursor) { tvSearchTerm = (TextView) view.findViewById(R.id.tvSearchTerm); final int position = cursor.getPosition(); if (cursorInBounds(position)) { final String term = mObjects.get(position); tvSearchTerm.setText(term); view.setTag(position); view.setOnClickListener(this); } else { // Something went wrong } } private boolean cursorInBounds(final int position) { return position < mObjects.size(); } @Override public void onClick(final View view) { final int position = (Integer) view.getTag(); if (cursorInBounds(position)) { final String selected = mObjects.get(position); Toast.makeText(getApplicationContext(), selected, Toast.LENGTH_SHORT).show(); // Do something } else { // Something went wrong } } } private MatrixCursor getCursor(final ArrayList<String> suggestions) { final String[] columns = new String[] { COLUMN_ID, COLUMN_TERM }; final Object[] object = new Object[] { 0, DEFAULT }; final MatrixCursor matrixCursor = new MatrixCursor(columns); for (int i = 0; i < suggestions.size(); i++) { object[0] = i; object[1] = suggestions.get(i); matrixCursor.addRow(object); } return matrixCursor; } } 

在我的实际代码中,我有一个自定义的接口,它使用从服务器获取的dynamic条件来填充ArrayList。 您将以这种方式更新数据集:

 @Override public void onDataReceived(final ArrayList<String> results) { suggestionsArray.clear(); suggestionsArray.addAll(results); final MatrixCursor matrixCursor = getCursor(suggestionsArray); suggestionsAdapter = new SuggestAdapter(this, matrixCursor, suggestionsArray); searchView.setSuggestionsAdapter(suggestionsAdapter); suggestionsAdapter.notifyDataSetChanged(); } 

我发现不是初始化一个空的游标或重新创build它,每次造成的问题。

希望能帮助到你。

在上面的方法中我注意到了一个问题。

当用户只input一个字符(例如"H" )时,从数据库获取条目并通过searchView.setSuggestionsAdapter(<adapter>)将适配器设置为searchView后,不会显示下拉列表。

只有在input第二个字符后(例如" ", "a" ),才会显示build议列表。 有人在观察这种行为吗?