先看结果:

相关的官方文档在这里: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;
} }

到目前为止的效果

该版本的完整代码: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.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())) {
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);
} }
}

到目前为止的效果

该版本的完整代码:SearchWidgetInAppBar - 完成搜索建议


嵌入AppBar并且带搜索建议的搜索框(Android)的更多相关文章

  1. ES[7.6.x]学习笔记(十二)高亮 和 搜索建议

    ES当中大部分的内容都已经学习完了,今天呢算是对前面内容的查漏补缺,把ES中非常实用的功能整理一下,在以后的项目开发中,这些功能肯定是对你的项目加分的,我们来看看吧. 高亮 高亮在搜索功能中是十分重要 ...

  2. solr入门之搜索建议的几种实现方式和最终选取实现思路

    上篇博客中我简单的讲了下solr自身的suggest模块来实现搜索建议.但是今天研究了下在solr自身的suggest中添加进去拼音来智能推荐时不时很方便.在次从网上搜集和整理思考了下该问题的解决. ...

  3. 各大搜索引擎智能提示API(JSONP跨域实现自动补全搜索建议)

    ---------------------------------------搜索引擎JSONP接口--------------------------------------------- 提示:U ...

  4. AJAX实现google搜索建议实战

    搜索建议实战的目标是为了输入搜索内容,动态的进行匹配,效果图如下: 整体思路: 在客户端搜索框中触发onkeyup事件, 随时向PHP服务器请求当前输入框中的内容, PHP服务器获取到keywords ...

  5. 【百度地图API】如何使用suggestion--下拉列表方式的搜索建议

    原文:[百度地图API]如何使用suggestion--下拉列表方式的搜索建议 摘要: 百度地图上有一个很强大的搜索建议功能,以下拉列表的方式展示出来.比如,输入“百度”,下拉列表中就会出现“北京市海 ...

  6. 一个简单的ExtJS搜索建议框

    封装的是一个Ext4.2的组件,继承并兼容于Ext的ComboBox. 实现原理非常easy,在 combo 中监听 keyup 事件就可以. 搜索建议的Combo.基本上全然兼容, 使用方式与Com ...

  7. Elasticsearch suggester搜索建议初步

    环境 Elasticsearch 2.3.5 Elasticsearch-ik-plugin 实现 搜索建议的对象 假设有以下两个json对象,需要对其中tags字段进行搜索建议: //对象Produ ...

  8. bootstrap suggest搜索建议插件

    近日因工作需要看了下此插件. 首先下载bootstrap js包.添加此插件的引用.注意css样式要引用,不能忘记. 前台页面代码,因为楼主做的是选项卡切换查询不同的结果. <tr> &l ...

  9. 5.电影搜索之 自动填充,也叫autocomplete、搜索建议!

    什么叫自动填充,用过百度的应该都知道!当你输入关键词之后,会有一个下拉的候选列表,都是与你输入的内容相关的,这个就是自动填充的搜索建议.一般的搜索引擎或者站内搜索都会有这个功能. 今天分享下这个功能的 ...

随机推荐

  1. ubuntu 中安装 ZED SDK 及结合ROS 的使用

    双目视觉(stereo vision),由于估计深度相对容易且稠密,在姿态估计和建图时容易初始化和估计尺度,所以在三维重建,SLAM等的应用中有这广泛的应用. ZED 作为近几年出现的商业化双目传感器 ...

  2. java代码,在linux上删除文件

    1.其实在linux上和window是一样的 2.path 传入的路径(直接从根目录到你的文件的位置) public static boolean delFile(String path) { log ...

  3. tusen 刷题

    //1.single number和变体 //2.lru lfu 3.给一个正整数集合,求一个和最大且能被3整除的子集.Follow up: 如果集合里有正有负 4.leetcode200-numbe ...

  4. 数据同步canal服务端HA配置

    canal服务端HA模式,本人并未使用过,为保证文章的完整性,从以下地址摘抄该部分内容,待以后验证及使用 https://github.com/alibaba/canal/wiki/AdminGuid ...

  5. Windows10 + eclipse + JDK1.8 + Apache Maven 3.6.0 + dl4j深度学习环境配置

    Windows10 + eclipse + JDK1.8 + Apache Maven 3.6.0 + dl4j深度学习环境配置 JDK下载安装请自行,并设置好环境变量1 查看Java版本C:\Use ...

  6. 无oracle客户端仅用plsql连接远程oracle

    1.在安装ORACLE服务器的机器上搜索下列文件,oci.dllocijdbc10.dllociw32.dllorannzsbb10.dlloraocci10.dlloraociei10.dllsql ...

  7. Android 连续按两次back键退出系统

    需求:在程序的首页,连续按两次back键退出Androd程序. 第一步:新建一个GApplication类继承Application,在GApplication中添加一个用于存放Activity的集合 ...

  8. 曾经的UCOSii

    首先记住一句话:实时操作系统,并非真的实时.操作系统必须有延时,一个系统执行好几个任务,实质是任务之间不停的切换,有延时才有切换任务的余地,如果没有.....应该都见识过卡机,任务切换不过来了 如果你 ...

  9. js获取图片的原始尺寸

    <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...

  10. vi学习

    刚开始学习vi,所以,一步一步开始 先贴出一个相关的学习链接https://www.cnblogs.com/ranjiewen/p/5901181.html 这个学习链接里面的东西还是比较详细的,但是 ...