嵌入AppBar并且带搜索建议的搜索框(Android)
2017-02-14 18:43
267 查看
先看结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202002/23/1efb6f1995bf56ef7308e0889c3f0bba.gif)
相关的官方文档在这里:Creating a Search Interface
Android官方提供了两种方式:
弹出一个Dialog,覆盖当前的Activity界面
在AppBar中扩展一个搜索框。
这个是上面动态图片展示的方式。以下介绍的是这种方式的实现。
官方建议:如果你写的程序是给Android 3.0 以上的设备使用,那么推荐使用AppBar的方式。
想要完成这个功能,你需要创建以下几个文件:
一个XML文件,用于配置搜索框。该文件路径:res/xml/searchable.xml
该文件会被系统用来创建SearchableInfo对象
一个用于接收搜索关键词并展示最终结果的Activity
一个内容提供器,用于提供搜索建议
分为两部分写。先完成搜索功能,再添加提供搜索建议的功能。
MainActivity.java
配置AppBar
SearchableActivity.java
根据Intent的Action,显示intent的内容
res/xml/searchable.xml
配置搜索框
res/menu/options_menu.xml
添加搜索框及配置AppBar
AndroidManifest.xml
配置SearchableActivity,使其接收ACTION_SEARCH的Intent
该版本的完整代码:SearchWidgetInAppBar - 完成基本的功能
之后添加“搜索建议”功能的时候,还需要对它进行修改。
现在创建一个简单地包含TextView的Activity就行了。这里将其命名为 SearchableActivity。
打开AndroidManifest.xml对该Activity进行配置:
由于intent-filter的设置,当接收到标记为ACTION_SEARCH的动作时,会启动该Activity。
SearchableActivity.java
作为示例,只展示要查询的单词是什么就可以了。
为了让其他Activity可以打开该Activity,在AndroidManifest.xml继续设置:
res/menu/options_menu.xml
设置的图标可以到Material icons下载。将解压后Android文件夹里面的所有文件复制到res/文件夹底下就行了。
app:actionViewClass="android.support.v7.widget.SearchView"
如果不设置这项,会导致错误。下面会提到。
collapseActionView是为了可以展开搜索框。
MainActivity.java
![](https://oscdn.geek-share.com/Uploads/Images/Content/202002/23/c46ef4c103f69fbf106e79cd7ec4d29d.gif)
该版本的完整代码:SearchWidgetInAppBar - 完成基本的功能
这一部分需要做的是:
添加一个内容提供器(ContentProvider),为搜索建议框提供数据
一张SQLite表,用于给内容提供器查询
修改searchable.xml文件,添加搜索建议的支持
该版本的完整代码:SearchWidgetInAppBar - 完成搜索建议
数据表:
这里的id字段设置为
word字段设置为
除此之外,还有一个字段suggestion。当你点击搜索建议中的数据时,系统会将该字段的数据放入Intent传送给SearchableActivity。
数据库:
由于ContentProvider需要Cursor作为结果,因此这里用了ORMLite作者所说的方法:Android Cursor with ORMLite to use in CursorAdapter
AndroidManifest.xml
当点击搜索建议时,传入Intent的Action是ACTION_VIEW。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202002/23/1efb6f1995bf56ef7308e0889c3f0bba.gif)
该版本的完整代码:SearchWidgetInAppBar - 完成搜索建议
![](https://oscdn.geek-share.com/Uploads/Images/Content/202002/23/1efb6f1995bf56ef7308e0889c3f0bba.gif)
相关的官方文档在这里:Creating a Search Interface
Android官方提供了两种方式:
弹出一个Dialog,覆盖当前的Activity界面
在AppBar中扩展一个搜索框。
这个是上面动态图片展示的方式。以下介绍的是这种方式的实现。
官方建议:如果你写的程序是给Android 3.0 以上的设备使用,那么推荐使用AppBar的方式。
想要完成这个功能,你需要创建以下几个文件:
一个XML文件,用于配置搜索框。该文件路径:res/xml/searchable.xml
该文件会被系统用来创建SearchableInfo对象
一个用于接收搜索关键词并展示最终结果的Activity
一个内容提供器,用于提供搜索建议
分为两部分写。先完成搜索功能,再添加提供搜索建议的功能。
第一部分:基本的搜索功能
这个部分完成五个文件的创建或修改:MainActivity.java
配置AppBar
SearchableActivity.java
根据Intent的Action,显示intent的内容
res/xml/searchable.xml
配置搜索框
res/menu/options_menu.xml
添加搜索框及配置AppBar
AndroidManifest.xml
配置SearchableActivity,使其接收ACTION_SEARCH的Intent
该版本的完整代码:SearchWidgetInAppBar - 完成基本的功能
searchable.xml
初始的xml:<?xml version="1.0" encoding="utf-8"?> <searchable xmlns:android="http://schemas.android.com/apk/res/android" android:label="@string/app_name" android:hint="@string/search_hint" > </searchable>
之后添加“搜索建议”功能的时候,还需要对它进行修改。
展示结果的Activity
当用户执行一个搜索的时候,系统会启动该Activity,并且传入搜索的词汇。这个词汇包含在Intent中,并且标记为ACTION_SEARCH动作。现在创建一个简单地包含TextView的Activity就行了。这里将其命名为 SearchableActivity。
打开AndroidManifest.xml对该Activity进行配置:
<application ... > <activity android:name=".SearchableActivity" > <intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/> </activity> ... </application>
由于intent-filter的设置,当接收到标记为ACTION_SEARCH的动作时,会启动该Activity。
SearchableActivity.java
public class SearchableActivity extends AppCompatActivity { TextView mTvWord = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_searchable); mTvWord = (TextView) findViewById(R.id.tv_word); Intent intent = getIntent(); if (Intent.ACTION_SEARCH.equals(intent.getAction())) { String query = intent.getStringExtra(SearchManager.QUERY); String text = getString(R.string.notice) + query; mTvWord.setText(text); } } }
作为示例,只展示要查询的单词是什么就可以了。
为了让其他Activity可以打开该Activity,在AndroidManifest.xml继续设置:
<?xml version="1.0" encoding="utf-8"?> <manifest ...> <application ...> ... <meta-data android:name="android.app.default_searchable" android:value=".SearchableActivity"/> </application> </manifest>
AppBar的设置
添加一个搜索按钮。res/menu/options_menu.xml
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/action_search" android:icon="@drawable/ic_search_white_24dp" android:title="@string/action_search" app:showAsAction="ifRoom|collapseActionView" app:actionViewClass="android.support.v7.widget.SearchView"/> <item android:id="@+id/action_settings" android:orderInCategory="100" android:title="@string/action_settings" app:showAsAction="never"/> </menu>
设置的图标可以到Material icons下载。将解压后Android文件夹里面的所有文件复制到res/文件夹底下就行了。
app:actionViewClass="android.support.v7.widget.SearchView"
如果不设置这项,会导致错误。下面会提到。
collapseActionView是为了可以展开搜索框。
MainActivity.java
public class MainActivity extends AppCompatActivity { ... @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.options_menu, menu); SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView(); searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); searchView.setIconifiedByDefault(false); searchView.setSubmitButtonEnabled(true); // 显示“开始搜索”的按钮 searchView.setQueryRefinementEnabled(true); // 提示内容右边提供一个将提示内容放到搜索框的按钮 return true; } }
到目前为止的效果
![](https://oscdn.geek-share.com/Uploads/Images/Content/202002/23/c46ef4c103f69fbf106e79cd7ec4d29d.gif)
该版本的完整代码:SearchWidgetInAppBar - 完成基本的功能
第二部分:添加搜索建议
官方文档:Adding Custom Suggestions这一部分需要做的是:
添加一个内容提供器(ContentProvider),为搜索建议框提供数据
一张SQLite表,用于给内容提供器查询
修改searchable.xml文件,添加搜索建议的支持
该版本的完整代码:SearchWidgetInAppBar - 完成搜索建议
数据库
这里用ORMLite作为例子。如果想用Android自带数据库,可以查看官方例子:SearchableDictionary数据表:
@DatabaseTable(tableName = "tb_def") public class Word { @DatabaseField(generatedId = true, columnName = COLUMN_ID) private int id; @DatabaseField(columnName = COLUMN_WORD) private String word; @DatabaseField(columnName = COLUMN_SUGGESTION) private String suggestion; public static final String COLUMN_ID = BaseColumns._ID; public static final String COLUMN_WORD = SearchManager.SUGGEST_COLUMN_TEXT_1; public static final String COLUMN_SUGGESTION = SearchManager.SUGGEST_COLUMN_INTENT_DATA; ... public Word(int id, String word, String suggestion) { this.id = id; this.word = word; this.suggestion = suggestion; } ... }
这里的id字段设置为
BaseColumns._ID是为了让ListView可以读取。搜索建议是显示在ListView上的。
word字段设置为
SearchManager.SUGGEST_COLUMN_TEXT_1是将该字段作为建议显示的文本。如果每个建议想显示两行数据,还有
SearchManager.SUGGEST_COLUMN_TEXT_2。更多内容可以见:SuggestionTable
除此之外,还有一个字段suggestion。当你点击搜索建议中的数据时,系统会将该字段的数据放入Intent传送给SearchableActivity。
数据库:
public class DatabaseHelper extends OrmLiteSqliteOpenHelper { ... public Cursor getSuggestionWords(String word) { QueryBuilder<Word, Integer> qb = getWordDao().queryBuilder(); CloseableIterator<Word> iterator = null; try { qb.distinct().where().like(Word.COLUMN_WORD, word + "%"); iterator = getWordDao().iterator(qb.prepare()); AndroidDatabaseResults results = (AndroidDatabaseResults) iterator.getRawResults(); return results.getRawCursor(); } catch (SQLException e) { e.printStackTrace(); } finally { if (iterator != null) { iterator.closeQuietly(); } } return null; } ... }
由于ContentProvider需要Cursor作为结果,因此这里用了ORMLite作者所说的方法:Android Cursor with ORMLite to use in CursorAdapter
创建内容提供器
public class DictionaryProvider extends ContentProvider { public static String AUTHORITY = "com.schaepher.memorywarehouse.DictionaryProvider"; private DatabaseHelper mDatabaseHelper = null; private static final int SEARCH_SUGGEST = 0; private static final UriMatcher mURIMatcher = buildUriMatcher(); private static UriMatcher buildUriMatcher() { UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST); matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST); return matcher; } @Override public boolean onCreate() { mDatabaseHelper = DatabaseHelper.getHelper(getContext()); return false; } @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { String query = uri.getLastPathSegment(); int i = mURIMatcher.match(uri); if (i == SEARCH_SUGGEST) { return mDatabaseHelper.getSuggestionWords(query); } else { throw new IllegalArgumentException("Unknown Uri: " + uri); } } @Override public String getType(@NonNull Uri uri) { int i = mURIMatcher.match(uri); if (i == SEARCH_SUGGEST) { return SearchManager.SUGGEST_MIME_TYPE; } else { throw new IllegalArgumentException("Unknown URL " + uri); } } ... }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest package="com.ftd.schaepher.memorywarehouse" xmlns:android="http://schemas.android.com/apk/res/android"> <application ...> ... <provider android:name=".DictionaryProvider" android:authorities="com.schaepher.memorywarehouse.DictionaryProvider" android:enabled="true" android:exported="false"> </provider> </application> </manifest>
searchable.xml
<?xml version="1.0" encoding="utf-8"?> <searchable xmlns:android="http://schemas.android.com/apk/res/android" android:label="@string/app_name" android:hint="@string/search_hint" android:searchSuggestAuthority="com.schaepher.memorywarehouse.DictionaryProvider" android:searchSuggestIntentAction="android.intent.action.VIEW"> </searchable>
当点击搜索建议时,传入Intent的Action是ACTION_VIEW。
SearchableActivity
SearchableActivity.javapublic class SearchableActivity extends AppCompatActivity { TextView mTvWord = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_searchable); mTvWord = (TextView) findViewById(R.id.tv_word); Intent intent = getIntent(); if (Intent.ACTION_SEARCH.equals(intent.getAction())) { mTvWord.append(intent.getStringExtra(SearchManager.QUERY)); } else if (Intent.ACTION_VIEW.equals((intent.getAction()))){ mTvWord.append(intent.getDataString()); } else { mTvWord.setText(R.string.word_not_found); } } }
到目前为止的效果
![](https://oscdn.geek-share.com/Uploads/Images/Content/202002/23/1efb6f1995bf56ef7308e0889c3f0bba.gif)
该版本的完整代码:SearchWidgetInAppBar - 完成搜索建议
相关文章推荐
- 嵌入AppBar并且带搜索建议的搜索框(Android)
- 嵌入AppBar并且带搜索建议的搜索框(Android)
- 嵌入AppBar并且带搜索建议的搜索框(Android)
- 嵌入AppBar并且带搜索建议的搜索框(Android)
- Android系统搜索对话框(浮动搜索框)的使用
- Android系统搜索对话框(浮动搜索框)的使用 (转)
- Android搜索框输入内容点击键盘的搜索按钮进行搜索
- Android 百度地图 SDK v3_3_0 (五) ---POI搜索和在线建议查询功能
- Android 点击搜索框 输入法回车键变成搜索键
- Android系统搜索对话框(浮动搜索框)的使用
- Android常用:手把手教你实现搜索框(含历史搜索记录)
- Android 的搜索机制 I-创建一个搜索框
- android 搜索自动匹配关键字并且标红
- Android系统搜索对话框(浮动搜索框)的使用
- Android系统搜索对话框(浮动搜索框)的使用
- android 自定义搜索框 + 搜索提示
- Android高仿百度地图公交与位置建议搜索(四)
- Android系统搜索对话框(浮动搜索框)的使用
- Android系统搜索对话框(浮动搜索框)的使用
- Android系统搜索对话框(浮动搜索框)的使用