Java 安卓:在没有可搜索活动的情况下提供最近的搜索建议?

Java 安卓:在没有可搜索活动的情况下提供最近的搜索建议?,java,android,searchview,Java,Android,Searchview,我有一个ActionBar SearchView,我能够成功地使用它进行搜索。android文档没有解释如何实现搜索建议。我不想有一个可搜索的活动 这是我的搜索代码: public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_add_song, menu); final SearchView searchView = (SearchView)

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

这是我的搜索代码:

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;
            }
        });
这适用于搜索,但我不知道如何实现最近的搜索查询建议。我该怎么做呢


谢谢。

好的,我把时间都花在这上面了。我从
SQLiteDatabase
创建了自己的简单的建议实现

我们将创建3个类,如下所示

  • main活动
    -用于测试数据库中的
    SearchView
    建议
  • SuggestionDatabase
    -这将存储您最近的搜索关键字
  • 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;
            }
        }
    
    }
    
    工作原理

  • 当用户点击搜索按钮时,将触发
    onquerytexsubmit()
    ,然后搜索关键字将保存在我们的数据库中。假设我们提交一个关键字“Hello”
  • 如果用户在
    SearchView
    中写入字符串,例如“Hel”或“H”,将调用
    onQueryTextChange()
    ,然后我们在
    SQLiteDatabase
    SuggestionDatabase
    )中搜索该关键字。如果“Hel”或“H”与“Hello”匹配,则通过在
    SuggestionSimpleCursorAdapter
    中设置返回的光标来显示查询结果,然后在
    SearchView
    中设置此适配器。这是照片
    3.当然,我们会点击“Hello”的建议,建议点击(int position)就会被调用。我们从
    SearchView
    的适配器(
    SuggestionSimpleCursorAdapter
    )获取
    SQLiteCursor
    对象,并从中获取建议文本,在
    SearchView
    对象中设置建议文本

    SQLiteCursor cursor = (SQLiteCursor) searchView.getSuggestionsAdapter().getItem(position);
    int indexColumnSuggestion = cursor.getColumnIndex( SuggestionsDatabase.FIELD_SUGGESTION);
    searchView.setQuery(cursor.getString(indexColumnSuggestion), false);
    
    如果我们使用
    SimpleCursorAdapter
    它也可以正常工作,但假设我们有这样的场景

  • 如果我们在智能手机上运行此程序并键入关键字“Hel”,建议将正确显示
  • 如果我们在横向旋转屏幕会怎么样?它将在全屏模式下切换,您仍然可以键入关键字
  • 建议中会发生什么?让我们看一下。

    看到奇怪的建议了吗?我们如何解决这个问题?通过覆盖
    convertToString(光标)
    返回
    CharSequence

     // 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(光标),结果如下

    这是数据库

    // 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) {
    
        }
    
      }
    
    }
    

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

    在上述方法中,我注意到一个问题

    当用户仅输入一个字符(例如
    “H”
    )时,在从数据库获取条目并通过
    searchView.setSuggestionAdapter()
    将适配器设置为searchView后,下拉列表不会显示

    只有在输入第二个字符(例如
    ,“a”
    )后,才会显示建议列表。
    还有其他人观察到这种行为吗?

    main活动中,从上面的
    onCreate方法中的
    类中首先使用此代码

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

    setThreshold(1)
    意味着它现在也可以从一个字符中搜索文本。

    我的需要更加简单-我不需要数据库,因为我在ArrayList中包含了许多我想要显示的建议

    下面是一个示例实现:

    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;
        }
    }
    
    import java.util.ArrayList;
    导入android.app.Activity;
    导入android.app.SearchManager;
    导入android.content.Context;
    导入android.database.Cursor;
    导入android.database.MatrixCursor;
    导入android.os.Bundle;
    导入android.view.LayoutInflater;
    导入android.view.Menu;
    导入android.view.MenuItem;
    导入android.view.view;
    导入android.view.view.OnClickListener;
    导入android.view.ViewGroup;
    导入android.widget.CursorAdapter;
    导入android.widget.SearchView;
    导入android.widget.SearchView.OnQueryTextListener;
    导入android.widget.TextView;
    导入android.widget.Toast;
    公共类ActivityTest在QueryTextListener上扩展活动实现{
    私有静态最终字符串列_ID=“_ID”;
    私有静态最终字符串列\u TERM=“TERM”;
    私有静态最终字符串DEFAULT=“DEFAULT”;
    私人搜索管理器搜索管理器;
    私有搜索视图搜索视图;
    私有菜单项搜索菜单项;
    私有建议适配器建议适配器;
    private final ArrayList SuggestionArray=新ArrayList();
    私有最终ArrayList dummyArray=新ArrayList();
    @凌驾
    创建时受保护的void(最终捆绑包savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //创建一些虚拟条目
    添加(“苹果”);
    添加(“橙子”);
    添加(“香蕉”);
    添加(“梨”);
    添加(“李子”);
    }
    @凌驾
    公共布尔onCreateOptions菜单(最终菜单){
    getMenuInflater().充气(R.menu.main,menu);
    searchManager=(searchManager)getSystemService(Context.SEARCH\u服务);
    searchMenuItem=menu.findItem(R.id.action\u search);
    searchView=(searchView)searchMenuItem.getActionView();
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName());
    setOnQueryTextListener(这个);
    最终MatrixCursor MatrixCursor=getCursor(SuggestionArray);
    SuggestionAdapter=新的SuggestionAdapter(this、matrixCursor、SuggestionArray);
    searchView.setSuggestionAdapter(SuggestionAdapter);
    suggestionsAdapter.notifyDataSetChanged();
    返回true;
    }
    @凌驾
    公共布尔onQueryTe
    
    @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();
    }