原文地址:http://developer.android.com/guide/topics/search/adding-custom-suggestions.html
如何为Suggestions声明intent
当用户在suggestion列表中选择了一个suggestion,系统就向你的searchable activity发送一个custom的Intent.你必须定义该intent的action和data.
声明intent的action
通常为intent声明的action都为ACTION_VIEW,它非常适合于打开一些东西,比如单词的定义,一个人的电话信息,或一个web页。
实际上可以声明intent的action为任何action,每个suggestion所对应的intent的action也可以各不相同。
为intent定义action有以下两种方式:
A,通过searchable配置文件的
android:searchSuggestIntentAction属性为所有的suggestion定义其intent的action。
比如,示例5:
<?xml version="1.0" encoding="utf-8"?> <searchable xmlns:android="http://schemas.android.com/apk/res/android" android:label="@string/app_label" android:hint="@string/search_hint" android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider" android:searchSuggestIntentAction="android.Intent.action.VIEW" > </searchable>
B、
通过sugestion table中的
SUGGEST_COLUMN_INTENT_ACTION来为每个suggestion定义其intent的action.
在你的suggestions table中加入
SUGGEST_COLUMN_INTENT_ACTION
列,然后针对每个suggestion把想要定义的intent的action放入其中(比如
"android.Intent.action.VIEW"
)
你还可以对这两种方式进行混合使用,先在s
earchable配置文件的
android:searchSuggestIntentAction属性为所有的suggestion定义其intent的action,然后再通过
SUGGEST_COLUMN_INTENT_ACTION定义intent的action来重写,
如果
SUGGEST_COLUMN_INTENT_ACTION
没有提供值,默认的就是
android:searchSuggestIntentAction属性所定义的值。
注意:如果你
在s
earchable配置文件没有定义
android:searchSuggestIntentAction属性,那么你必须在
SUGGEST_COLUMN_INTENT_ACTION中提供值来定义intent的action.
声明intent的data
当用户在suggestion列表中选择了一个suggestion,系统就向你的searchable activity发送一个custom的Intent.这个intent除了包含action外,还必须携带data,以便你的activity确定是哪个suggestion被选中了。特别需要注意的是该data必须和你的suggestion是唯一对应的,比如说你的SQLite table中的row id就是和suggestion唯一对应的。当收到该intent时,你可以通过
getData()或
getDataString()提取它携带的数据。
你可以通过下面的2种方式定义intent携带的data:
A,通过
SUGGEST_COLUMN_INTENT_DATA列为你的每个suggestoin定义其
intent携带的data。
为了给每个suggestion的intent提供必要的数据信息,你可以在suggestions table中包含
SUGGEST_COLUMN_INTENT_DATA,然后把每个suggestion其对应的row ID放入其中。你在该列定义的data将在发送intent时被附到intent上进行传送。然后你可以通过intent的
getData()或
getDataString()提取携带的数据。
注意:使用row ID作为intent的data是最简单的方式,而使用row ID做intent的data最简单的方式是把
SUGGEST_COLUMN_INTENT_DATA列作为row ID column的别名列,具体请参照 Searchable Dictionary sample app
B,把data的URL分成2部分:一部分对所有的suggestion都是一样的,另一部分和每个suggestions是唯一对应的。第一部分通过
s
earchable配置文件的
android:searchSuggestintentData属性来定义,第二部分通过sugestion table中的
SUGGEST_COLUMN_INTENT_DATA_ID来定义
在searchable配置文件的android:searchSuggestintentData属性中定义data URL的相同部分,可以参考下例:
示例6:
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_label"
android:hint="@string/search_hint"
android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
android:searchSuggestIntentAction="android.intent.action.VIEW"
android:searchSuggestIntentData="content://com.example/datatable" >
</searchable>
剩下的针对每个suggestions的data URL部分就可以在通过sugestion table中的
SUGGEST_COLUMN_INTENT_DATA_ID来定义.
当用户选择了一个suggestion,那么android:searchSuggestIntentData加上"/",再加上
SUGGEST_COLUMN_INTENT_DATA_ID列的值就生成了完整的data URL,然后它被携带在intent上来进行传送。你可以通过
intent的
getData()来提取其URI值。
携带更多的Data
你可以通过
SUGGEST_COLUMN_INTENT_EXTRA_DATA
,
来携带更的数据,它可以携带更多关于suggestion的信息。你在intent的extra data中通过
EXTRA_DATA_KEY提取它。
处理intent
当用户在suggestion列表中选择了一个suggestion,其对应的intent就会发送到你的searchable activity。因此在searchable activity中,你除了要处理
ACTION_SEARCH
intent,还需要
处理该intent.下面的示例7就是在
onCreate()处理这两intent的一个例子:
示例7:
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
// Handle the normal search query case
String query = intent.getStringExtra(SearchManager.QUERY);
doSearch(query);
} else if (
Intent.ACTION_VIEW.equals(intent.getAction())
) {
// Handle a suggestions click (because the suggestions all use ACTION_VIEW)
Uri data = intent.getData();
showResult(data);
}
在上面的例子中suggestion intent的action是 ACTION_VIEW,
它携带的data的Uri说明如何取得该suggestion。这里的Uri是通过
android:searchSuggestIntentData和
SUGGEST_COLUMN_INTENT_DATA_ID例子合成的(参照示例6)。Uri又被传送到showResult()方法,该方法通过Uri在content Provider中提取suggestion的详细信息。
注意:你不需要在你的mainfest配置文件中为你的
searchable activity的过滤器中加入
android:searchSuggestIntentAction属性或 SUGGEST_COLUMN_INTENT_ACTION定义的intent,因为系统是通过名字来启动你的searchable activity和传送intent的。
改写query text
如果用户在suggestion列表中通过导航键来移动时,默认的是不会修改输入框的query text。然而此时你可以用suggestion列表中获得焦点的suggestoin所指定的内容取代输入框的query text。这样用户就可以看到建议的内容,并进行编辑,然后进行搜索。
你可以用以下的几种方式改写query text:
A:
在searchable配置文件中把
android:searchMode
属性设置为"
queryRewriteFromText
",这样suggestion的 SUGGEST_COLUMN_TEXT_1
列将用于改写query text
B:
在searchable配置文件中把
android:searchMode
属性设置为"
queryRewriteFromData
",这样suggestion的 SUGGEST_COLUMN_INTENT_DATA
列将用于改写query text。但是这时 SUGGEST_COLUMN_INTENT_DATA
的值必须是对用户可见的URI或其他格式,不能使用内部的URI。
C:
在suggestions table中提供一个unique query字符串放在 SUGGEST_COLUMN_QUERY
列中,那么它将改写query text(它将重写前面的2种实现方式)。
管理Quick Search Box suggestion shortcuts
当一个suggestion在
Quick Search Box
中被用户选中以后,系统会自动为它做个shortcut.这些shortcut的suggestion是从你的
content provider
拷贝而来的,这样用户就能快速的访问suggestion,而不每次都重新查询。
默认情况下,
Quick Search Box
对你的所有suggestion都是这样处理的。但是你的suggestion的数据可能改变,这时你就需要重新查询来更新shortcut。举例来说你的,如果你的data是动态变化的,比如联系人的在线状态,那么当向用户显现suggestion的时候,你需要更新shortcut。为此,你需要在你的suggestions table中包含 SUGGEST_COLUMN_SHORTCUT_ID。
对于该列,你可以通过下面的几种方式设定:
A
、让Quick Search Box在你的content provider再次进行查询,以得到shortcut的最新版本。
如果你在 SUGGEST_COLUMN_SHORTCUT_ID列中提供了值,那么每次shortcut进行显示的时候,都将再次进行更新查询,以得到最新的版本。在查询返回前,shortcut都用最近数据进行显示,查询返回之后就用查询到的最新数据进行显示。在进行更新查询时,这时传入的URI路径为 SUGGEST_URI_PATH_SHORTCUT(而不是 SUGGEST_URI_PATH_QUERY)你返回的Cursor包含的suggestion必须和最初的是同一个,或为空。如果为空的说明该shortcut已经变得非法,这时和它对应的suggestion将消失,shortcut也将被移除。
如果suggestion更新需要很才时间,比如通过网络来更新,你可以把suggestions table的 SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING设置为"true",那么在更新完成之前系统将在右边显示一个progress spinner。
否则将不显示progress spinner。
B、禁用suggestion的shortcut功能。如果把
SUGGEST_COLUMN_SHORTCUT_ID
列的值设置为
SUGGEST_NEVER_MAKE_SHORTCUT,那么系统将不会对suggestion进行shortcut。
C、默认的shortcut行为。
如果
SUGGEST_COLUMN_SHORTCUT_ID为空的话,系统还是会开启shortcut,但是shortcut不会被更新
如果你的suggestion永远不改变的话,那么就不用 SUGGEST_COLUMN_SHORTCUT_ID列。
注意:
现在所知道的shortcut很有意义在于,如果我们在searchable.xml配置文件中设置
android:searchSuggestThreshold
,比如android:searchSuggestThreshold="1"(表示只要用户至上输入了1个字符才查询显示suggestion),那么在用户没有输入任何字符的时候显示的就是shortcut.
SearchableDictionary
例子就是这样的。