添加自定义搜索建议

您可以根据 Android 搜索对话框中的近期搜索查询提供搜索建议,或者 搜索微件。例如,如果用户查询“小狗”查询会以建议的形式显示 您可以再次输入相同的查询图 1 显示了包含近期查询的搜索对话框示例 建议。

在开始之前,请实现用于基本搜索的搜索对话框或搜索微件 。要了解具体方法,请参阅 创建搜索界面

基础知识

图 1. 包含近期查询的搜索对话框的屏幕截图 建议。

近期查询建议是已保存的搜索。当用户选择一条建议后, activity 会收到 ACTION_SEARCH intent 并将其建议为您的可搜索 activity 已经处理的搜索查询。

要提供近期查询建议,您需要执行以下操作:

  • 实现可搜索 activity。
  • 创建可以扩展 SearchRecentSuggestionsProvider 并在应用清单中进行声明
  • 使用有关提供以下内容的 content provider 的信息来修改可搜索配置: 搜索建议。
  • 每次执行搜索时,都将查询保存到内容提供程序。

就像 Android 系统显示搜索对话框一样,它会显示以下搜索建议 对话框或搜索 widget。由您提供系统从中检索建议的来源。

当系统发现您的 Activity 可搜索并提供搜索建议时, 在用户输入查询时会发生以下情况:

  1. 系统获取搜索查询文本(用户开始输入的任何内容),然后 对包含您的建议的内容提供程序执行查询。
  2. 您的内容提供程序会返回 指向全部的 Cursor 与搜索查询文本匹配的建议。
  3. 系统会显示 Cursor 提供的建议列表。

显示近期查询建议后,可能会发生以下情况:

  • 如果用户键入其他键或以任何方式更改查询,则上述步骤为 并更新建议列表。
  • 如果用户执行此搜索,系统会忽略建议,并将搜索传递给 可搜索 activity。ACTION_SEARCH
  • 如果用户选择某条建议,系统会向您的 activity 传递一个 ACTION_SEARCH intent。 使用建议文本作为查询的可搜索 activity。

您为 content provider 扩展的 SearchRecentSuggestionsProvider 类 会自动执行前面步骤中的工作,因此只需编写少量代码。

创建 content provider

近期查询建议所需的 content provider 是 SearchRecentSuggestionsProvider。此类将为您完成所有操作。您只需要 编写一个执行一行代码的类构造函数。

例如,以下是针对近期查询的内容提供程序的完整实现 建议:

Kotlin

class MySuggestionProvider : SearchRecentSuggestionsProvider() {
    init {
        setupSuggestions(AUTHORITY, MODE)
    }

    companion object {
        const val AUTHORITY = "com.example.MySuggestionProvider"
        const val MODE: Int = SearchRecentSuggestionsProvider.DATABASE_MODE_QUERIES
    }
}

Java

public class MySuggestionProvider extends SearchRecentSuggestionsProvider {
    public final static String AUTHORITY = "com.example.MySuggestionProvider";
    public final static int MODE = DATABASE_MODE_QUERIES;

    public MySuggestionProvider() {
        setupSuggestions(AUTHORITY, MODE);
    }
}

setupSuggestions() 会传递搜索授权方的名称和数据库模式。搜索授权方可以是 字符串,但最佳做法是为您的内容提供程序使用完全限定名称,例如 软件包名称,后跟提供程序的类名称。例如 "com.example.MySuggestionProvider"

数据库模式必须包含 DATABASE_MODE_QUERIES 并且可以选择性地包含 DATABASE_MODE_2LINES, 系统会在建议表格中添加一列 建议。如果您想在每条建议中提供两行内容,请参阅以下示例:

Kotlin

const val MODE: Int = DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES

Java

public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;

在应用清单中声明 content provider,使用 您的 SearchRecentSuggestionsProvider 类和可搜索配置中。例如:

<application>
    <provider android:name=".MySuggestionProvider"
              android:authorities="com.example.MySuggestionProvider" />
    ...
</application>

修改可搜索配置

要将系统配置为使用建议提供程序,请将 android:searchSuggestAuthorityandroid:searchSuggestSelection 属性添加到可搜索配置文件中的 <searchable> 元素。例如:

<?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.MySuggestionProvider"
    android:searchSuggestSelection=" ?" >
</searchable>

android:searchSuggestAuthority 的值必须是 与 content provider 中使用的授权方完全匹配的内容提供程序,例如 "com.example.MySuggestionProvider"

android:searchSuggestSelection 的值前面必须为单个问号 由空格添加:" ?"。这是 SQLite 选择参数的占位符, 自动替换为用户输入的查询文本。

保存查询

要填充您的近期查询集合,请添加您的可搜索渠道收到的每个查询 将活动记录发送到您的 SearchRecentSuggestionsProvider。为此,请创建一个 SearchRecentSuggestions 并致电 saveRecentQuery() 每当可搜索 Activity 收到查询时触发。例如,以下代码段展示了如何保存查询 进行 onCreate() 方法:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main)

    if (Intent.ACTION_SEARCH == intent.action) {
        intent.getStringExtra(SearchManager.QUERY)?.also { query ->
            SearchRecentSuggestions(this, MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE)
                    .saveRecentQuery(query, null)
        }
    }
}

Java

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Intent intent  = getIntent();

    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);
        SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
                MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);
        suggestions.saveRecentQuery(query, null);
    }
}

SearchRecentSuggestionsProvider 构造函数需要 授权方和数据库模式。

saveRecentQuery() 方法将搜索查询字符串作为第一个参数 和(可选)要作为建议第二行包含的第二个字符串或 null。第二个 参数仅在您使用 DATABASE_MODE_2LINES。如果您启用两行模式,则查询文本将与 第二行。

清除建议数据

为了保护用户的隐私,请始终为用户提供清除近期查询的方法 建议。要清除查询历史记录,请调用 clearHistory()。 例如:

Kotlin

SearchRecentSuggestions(this, HelloSuggestionsProvider.AUTHORITY, HelloSuggestionsProvider.MODE)
        .clearHistory()

Java

SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
        HelloSuggestionProvider.AUTHORITY, HelloSuggestionProvider.MODE);
suggestions.clearHistory();

通过您选择的“清除搜索记录”来执行这项操作菜单项、偏好设置项目或按钮。 提供确认对话框,验证用户是否要删除搜索记录。