Google 致力于为黑人社区推动种族平等。查看具体举措

创建搜索界面

当您准备好向应用添加搜索功能时,Android 可通过显示在 Activity 窗口顶部的搜索对话框或您可以在布局中插入的搜索微件来帮助您实现界面。搜索对话框和搜索微件均可将用户的搜索查询传递给应用中的特定 Activity。这样,用户就可以从提供了搜索对话框或搜索微件的任何 Activity 发起搜索,而系统会启动相应的 Activity 来执行搜索并显示结果。

搜索对话框和搜索微件提供的其他功能包括:

  • 语音搜索
  • 基于近期查询的搜索建议
  • 与应用数据中的实际结果相符的搜索建议

本指南将为您介绍如何设置应用来提供搜索界面,以在 Android 系统的协助下使用搜索对话框或搜索微件传递搜索查询。

相关资源:

基础知识

图 1. 应用的搜索对话框的屏幕截图。

在开始之前,您应决定是使用搜索对话框还是搜索微件来实现搜索界面。它们两者提供相同的搜索功能,但方式略有不同:

  • 搜索对话框是一个由 Android 系统控制的界面组件。由用户激活后,搜索对话框将显示在 Activity 的顶部,如图 1 所示。

    Android 系统控制搜索对话框中的所有事件。当用户提交查询时,系统会将该查询传递给您指定用来处理搜索的 Activity。该对话框还可以在用户输入内容的同时提供搜索建议。

  • 搜索微件是一个 SearchView 实例,您可以将其放置在布局中的任意位置。默认情况下,搜索微件的行为类似于标准的 EditText 微件,它没有什么特殊的作用,但您可以对其进行配置,以使 Android 系统处理所有输入事件,将查询传递给适当的 Activity,并提供搜索建议(就像搜索对话框一样)。

    注意:如果需要,您可以使用各种回调方法和监听器自行处理搜索微件中的所有用户输入。不过,本文档重点介绍如何将搜索微件与系统集成以实现辅助搜索。如果您要自行处理所有用户输入,请阅读 SearchView 及其嵌套接口的参考文档。

当用户从搜索对话框或搜索微件中执行搜索时,系统会创建一个 Intent 并将用户查询存储在其中。然后,系统会启动您已声明用来处理搜索的 Activity(即“可搜索 Activity”),并向其传递该 intent。要设置您的应用来执行这种辅助搜索,您需要以下几项:

  • 可搜索配置

    一个 XML 文件,用于为搜索对话框或搜索微件配置一些设置,其中包括语音搜索、搜索建议和搜索框的提示文本等功能的设置。

  • 可搜索 Activity

    接收搜索查询、搜索数据并显示搜索结果的 Activity

  • 搜索界面,由以下两项中的任意一项提供:
    • 搜索对话框

      默认情况下,搜索对话框处于隐藏状态,但是当您调用 onSearchRequested() 时(当用户按您的搜索按钮时),它会显示在屏幕的顶部。

    • 或者,SearchView 微件

      使用搜索微件,您可以将搜索框放在 Activity 中的任意位置。您通常应将 SearchView 用作应用栏中的操作视图,而不是将其放在 Activity 布局中。

本文档的其余部分将为您介绍如何创建可搜索配置和可搜索 Activity,以及如何使用搜索对话框或搜索微件来实现搜索界面。

创建可搜索配置

您首先需要的是一个名为可搜索配置的 XML 文件。它可以为搜索对话框或搜索微件配置界面的某些方面,并定义建议和语音搜索等功能的行为方式。此文件一直以来名为 searchable.xml,并且必须保存在 res/xml/ 项目目录中。

注意:系统使用此文件来实例化 SearchableInfo 对象,但您无法在运行时自行创建此对象,您必须在 XML 中声明可搜索配置。

可搜索配置文件必须包含 <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" >
    </searchable>
    

android:label 属性是唯一一个必需的属性。它指向一个字符串资源,该资源应该是应用名称。此标签实际上对用户不可见,直到您为快速搜索框启用搜索建议。启用搜索建议后,此标签会显示在系统设置的可搜索项的列表中。

虽然并非强制性要求,但我们建议您始终添加 android:hint 属性,该属性会在用户输入查询之前在搜索框中提供一个提示字符串。提示非常重要,因为它可以为用户提供重要的线索,告知用户他们可以搜索哪些内容。

提示:为了与其他 Android 应用保持一致,您应将 android:hint 字符串的格式设为“搜索 <content-or-product>”。例如,“搜索歌曲和音乐人”或“搜索 YouTube”。

<searchable> 元素接受几个其他属性。不过,在添加搜索建议语音搜索等功能之前,您并不需要大多数属性。如需详细了解可搜索配置文件,请参阅可搜索配置参考文档。

创建可搜索 Activity

可搜索 Activity 是您的应用中基于查询字符串执行搜索并显示搜索结果的 Activity

当用户在搜索对话框或搜索微件中执行搜索时,系统会启动可搜索 Activity,并通过 ACTION_SEARCH 操作向其传递 Intent 中的搜索查询。可搜索 Activity 会从 intent 的 QUERY extra 中检索查询,然后搜索数据并显示结果。

由于您可以在应用中的其他任何 Activity 中添加搜索对话框或搜索微件,因此系统必须知道哪个 Activity 是可搜索 Activity,它才能正确传递搜索查询。所以,您必须先在 Android 清单文件中声明可搜索 Activity。

声明可搜索 Activity

如果您还没有用来执行搜索并显示结果的 Activity,请创建一个。您还不需要实现搜索功能,只需创建一个可以在清单中声明的 Activity 即可。在清单的 <activity> 元素内:

  1. <intent-filter> 元素中声明要接受 ACTION_SEARCH intent 的 Activity。
  2. <meta-data> 元素中指定要使用的可搜索配置。

例如:

    <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>
    

<meta-data> 元素必须包含值为 "android.app.searchable"android:name 属性以及引用可搜索配置文件的 android:resource 属性(在本例中,它引用 res/xml/searchable.xml 文件)。

注意<intent-filter> 不需要具有 DEFAULT 值(您通常会在 <activity> 元素中看到)的 <category>,因为系统会使用相应的组件名称将 ACTION_SEARCH intent 明确传递给可搜索 Activity。

执行搜索

在清单中声明可搜索 Activity 之后,在可搜索 Activity 中执行搜索涉及三个步骤:

  1. 接收查询
  2. 搜索数据
  3. 显示结果

一直以来,搜索结果都应显示在 ListView 中,因此您可能希望可搜索 Activity 扩展 ListActivity。它包含具有单个 ListView 的默认布局,并提供了几种便捷方法来使用 ListView

接收查询

当用户从搜索对话框或搜索微件中执行搜索时,系统会启动可搜索 Activity 并向其发送 ACTION_SEARCH intent。此 intent 在 QUERY 字符串 extra 中携带搜索查询。您必须在该 Activity 启动时检查此 intent 并提取相应的字符串。例如,以下代码段说明了您如何在可搜索 Activity 启动时获取搜索查询:

Kotlin

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

        // Verify the action and get the query
        if (Intent.ACTION_SEARCH == intent.action) {
            intent.getStringExtra(SearchManager.QUERY)?.also { query ->
                doMySearch(query)
            }
        }
    }
    

Java

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

        // Get the intent, verify the action and get the query
        Intent intent = getIntent();
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
          String query = intent.getStringExtra(SearchManager.QUERY);
          doMySearch(query);
        }
    }
    

QUERY 字符串始终随附于 ACTION_SEARCH intent。在本例中,系统检索了查询并将其传递给执行实际搜索操作的本地 doMySearch() 方法。

搜索数据

存储和搜索数据的过程对于您的应用来说是独一无二的。您可以通过多种方式存储和搜索数据,但本指南没有为您介绍如何存储和搜索数据。您应根据自己的需求和数据格式来仔细考虑如何存储和搜索数据。不过,下面给出了一些提示,您或许能够加以参考:

  • 如果您的数据存储在设备上的 SQLite 数据库中,执行全文搜索(使用 FTS3,而不是 LIKE 查询)可以在全部文本数据中进行更强大的搜索,并且可以明显加快生成结果的速度。如需了解 FTS3,请参阅 sqlite.org;如需了解 Android 平台上的 SQLite,请参阅 SQLiteDatabase 类。
  • 如果您的数据是在线存储的,则用户的数据连接可能会妨碍感知到的搜索性能。您可能希望在搜索返回结果之前显示一个旋转的进度轮。如需查看网络 API 的参考,请参阅 android.net;如需了解如何显示进度轮,请参阅创建进度对话框

显示结果

无论您的数据位于何处,也不管您如何进行搜索,我们都建议您通过 Adapter 将搜索结果返回到可搜索 Activity。这样,您便可以在 ListView 中轻松显示所有搜索结果。如果您的数据来自 SQLite 数据库查询,您可以使用 CursorAdapter 将结果应用于 ListView。如果您的数据采用其他某种类型的格式,则您可以创建 BaseAdapter 的扩展。

Adapter 将一组数据中的每一项绑定到一个 View 对象。将 Adapter 应用于 ListView 后,每段数据都作为单独的视图插入到列表中。Adapter 只是一个接口,因此需要 CursorAdapter(用于绑定来自 Cursor 的数据)等实现。如果现有实现都不适用于您的数据,则您可以通过 BaseAdapter 自行实现。

您可能希望可搜索 Activity 扩展 ListActivity。然后,您可以调用 setListAdapter(),并向其传递绑定到您的数据的 Adapter。这样会将所有搜索结果注入 Activity ListView

如需获得关于在列表中显示结果的更多帮助,请参阅 ListActivity 文档。

使用搜索对话框

搜索对话框在屏幕顶部提供了一个浮动搜索框,应用图标显示在左侧。搜索对话框可以在用户输入内容时提供搜索建议,当用户执行搜索时,系统会将搜索查询发送到用来执行搜索的可搜索 Activity。不过,如果您要为搭载 Android 3.0 的设备开发应用,则应考虑改用搜索微件(请参阅使用搜索微件部分)。

默认情况下,搜索对话框始终处于隐藏状态,直到用户将其激活。您的应用可以通过调用 onSearchRequested() 来激活搜索对话框。不过,在您为 Activity 启用搜索对话框之前,此方法不起作用。

要启用搜索对话框,您必须向系统指明哪个可搜索 Activity 应从搜索对话框接收搜索查询,以便执行搜索。例如,在介绍如何创建可搜索 Activity 的上一部分中,创建了一个名为 SearchableActivity 的可搜索 Activity。如果您希望一个名为 OtherActivity 的单独 Activity 显示搜索对话框并将搜索传递给 SearchableActivity,则必须在清单中声明 SearchableActivity 是用于 OtherActivity 中的搜索对话框的可搜索 Activity。

要为某个 Activity 的搜索对话框声明可搜索 Activity,请在相应 Activity 的 <activity> 元素内添加 <meta-data> 元素。<meta-data> 元素必须包含用于指定可搜索 Activity 的类名的 android:value 属性以及值为 "android.app.default_searchable"android:name 属性。

例如,下面是可搜索 Activity SearchableActivity 和另一个 Activity OtherActivity 的声明,后者使用 来执行在其搜索对话框中进行的搜索:

    <application ... >
        <!-- this is the searchable activity; it performs searches -->
        <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>

        <!-- this activity enables the search dialog to initiate searches
             in the SearchableActivity -->
        <activity android:name=".OtherActivity" ... >
            <!-- enable the search dialog to send searches to SearchableActivity -->
            <meta-data android:name="android.app.default_searchable"
                       android:value=".SearchableActivity" />
        </activity>
        ...
    </application>
    

由于 OtherActivity 现在包含 <meta-data> 元素来声明要用于搜索的可搜索 Activity,因此该 Activity 已启用搜索对话框。当用户在此 Activity 中时,onSearchRequested() 方法会激活搜索对话框。当用户执行搜索时,系统会启动 SearchableActivity 并向其传递 ACTION_SEARCH intent。

注意:默认情况下,可搜索 Activity 本身会提供搜索对话框,因此您无需向 SearchableActivity 添加此声明。

如果您希望应用中的每个 Activity 都提供搜索对话框,请将上面的 <meta-data> 元素作为 <application> 元素(而不是每个 <activity>)的子级插入。这样,每个 Activity 都会继承相应的值、提供搜索对话框,并将搜索传递给同一可搜索 Activity。(如果您有多个可搜索 Activity,您可以通过在单个 Activity 内添加不同的 <meta-data> 声明来替换默认的可搜索 Activity。)

现在为您的 Activity 启用了搜索对话框,您的应用已经可以执行搜索了。

调用搜索对话框

虽然某些设备提供了专用的搜索按钮,但该按钮的行为可能因设备不同而异,而且许多设备根本不提供搜索按钮。因此,使用搜索对话框时,您必须在界面中提供一个搜索按钮,该按钮通过调用 onSearchRequested() 来激活搜索对话框。

例如,您应在选项菜单或界面布局中添加一个调用 onSearchRequested() 的搜索按钮。为了与 Android 系统及其他应用保持一致,您应使用操作栏图标包中提供的 Android 搜索图标为您的按钮添加标签。

注意:如果您的应用使用应用栏,则您不应将搜索对话框用于搜索界面,而应将搜索微件用作应用栏中的可收起视图。

您还可以启用“输入字词进行搜索”功能,启用该功能后,当用户开始在键盘上输入字词时,会激活搜索对话框 - 按键会插入到搜索对话框中。您可以通过在 Activity 的 onCreate() 方法执行期间调用 setDefaultKeyMode (DEFAULT_KEYS_SEARCH_LOCAL),在 Activity 中启用输入字词进行搜索功能。

搜索对话框对 Activity 生命周期的影响

搜索对话框是一个浮动在屏幕顶部的 Dialog。它不会导致 Activity 堆栈发生任何变化,因此当搜索对话框出现时,不会调用任何生命周期方法(如 onPause())。Activity 只是会失去输入焦点,因为系统会将输入焦点提供给搜索对话框。

如果您希望在激活搜索对话框时收到通知,请替换 onSearchRequested() 方法。当系统调用此方法时,表明 Activity 已将输入焦点移交给搜索对话框,因此您可以执行任何适合该事件的操作(如暂停游戏)。除非您传递搜索上下文数据(下文将对此进行介绍),否则应通过调用超类实现来结束该方法。例如:

Kotlin

    override fun onSearchRequested(): Boolean {
        pauseSomeStuff()
        return super.onSearchRequested()
    }
    

Java

    @Override
    public boolean onSearchRequested() {
        pauseSomeStuff();
        return super.onSearchRequested();
    }
    

如果用户通过按“返回”按钮取消搜索,则搜索对话框会关闭,并且 Activity 会重新获得输入焦点。您可以进行注册,以便在使用 setOnDismissListener() 和/或 setOnCancelListener() 关闭搜索对话框时收到通知。您应该只需要注册 OnDismissListener,因为每当搜索对话框关闭时都会调用它。OnCancelListener 仅适用于用户明确退出搜索对话框的事件,因此执行搜索时(在这种情况下,搜索对话框会自然消失)不会调用它。

如果当前 Activity 不是可搜索 Activity,则用户执行搜索后,会触发正常的 Activity 生命周期事件(当前 Activity 会接收 onPause() 等等,如 Activity 文档中所述)。不过,如果当前 Activity 是可搜索 Activity,则会发生以下两种情况之一:

  1. 默认情况下,可搜索 Activity 会随着对 onCreate() 的调用接收 ACTION_SEARCH intent,并且系统会将该 Activity 的一个新实例置于 Activity 堆栈的顶部。Activity 堆栈中现在有可搜索 Activity 的两个实例(因此,按“返回”按钮时,会返回到可搜索 Activity 的上一个实例,而不是退出可搜索 Activity)。
  2. 如果将 android:launchMode 设为 "singleTop",则可搜索 Activity 会随着对 onNewIntent(Intent) 的调用(在此处传递新的 ACTION_SEARCH intent)接收 ACTION_SEARCH intent。例如,以下代码段说明了您如何处理这种情况,在本例中,可搜索 Activity 的启动模式为 "singleTop"

    Kotlin

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.search)
            handleIntent(intent)
        }
    
        override fun onNewIntent(intent: Intent) {
            setIntent(intent)
            handleIntent(intent)
        }
    
        private fun handleIntent(intent: Intent) {
            if (Intent.ACTION_SEARCH == intent.action) {
                intent.getStringExtra(SearchManager.QUERY)?.also { query ->
                    doMySearch(query)
                }
            }
        }
        

    Java

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.search);
            handleIntent(getIntent());
        }
    
        @Override
        protected void onNewIntent(Intent intent) {
            setIntent(intent);
            handleIntent(intent);
        }
    
        private void handleIntent(Intent intent) {
            if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
              String query = intent.getStringExtra(SearchManager.QUERY);
              doMySearch(query);
            }
        }
        

    与介绍如何执行搜索的部分中的示例代码相比,用于处理搜索 intent 的所有代码现在都在 handleIntent() 方法中,因此 onCreate()onNewIntent() 均可执行该代码。

    当系统调用 onNewIntent(Intent) 时,Activity 尚未重新启动,因此 getIntent() 方法返回的 intent 与随 onCreate() 接收的 intent 相同。这就是您应该在 onNewIntent(Intent) 内调用 setIntent(Intent) 的原因(为的是您将来调用 getIntent() 时会更新 Activity 保存的 intent)。

使用 "singleTop" 启动模式的第二种情况通常比较理想,因为用户很有可能在完成一项搜索后执行其他搜索,如果您的应用创建可搜索 Activity 的多个实例,会带来糟糕的用户体验。因此,我们建议您在应用清单中将可搜索 Activity 设为 "singleTop" 启动模式。例如:

    <activity android:name=".SearchableActivity"
              android:launchMode="singleTop" >
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data android:name="android.app.searchable"
                          android:resource="@xml/searchable"/>
      </activity>
    

传递搜索上下文数据

在某些情况下,您可以针对所做的每项搜索来对可搜索 Activity 中的搜索查询进行必要的优化。不过,如果您要根据用户从中执行搜索的 Activity 来优化搜索条件,则可以在系统发送到可搜索 Activity 的 intent 中提供额外的数据。您可以在 ACTION_SEARCH intent 中包含的 APP_DATA Bundle 中传递额外的数据。

要将此类数据传递给可搜索 Activity,请为用户可从中执行搜索的 Activity 替换 onSearchRequested() 方法,创建一个包含额外数据的 Bundle,并调用 startSearch() 以激活搜索对话框。例如:

Kotlin

    override fun onSearchRequested(): Boolean {
        val appData = Bundle().apply {
            putBoolean(JARGON, true)
        }
        startSearch(null, false, appData, false)
        return true
    }
    

Java

    @Override
    public boolean onSearchRequested() {
         Bundle appData = new Bundle();
         appData.putBoolean(SearchableActivity.JARGON, true);
         startSearch(null, false, appData, false);
         return true;
     }
    

返回“true”表示您已成功处理此回调事件并已调用 startSearch() 来激活搜索对话框。用户提交查询后,系统会将该查询连同您已添加的数据一起传递给可搜索 Activity。您可以从 APP_DATA Bundle 中提取额外的数据来优化搜索。例如:

Kotlin

    val jargon: Boolean = intent.getBundleExtra(SearchManager.APP_DATA)?.getBoolean(JARGON) ?: false
    

Java

    Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
    if (appData != null) {
        boolean jargon = appData.getBoolean(SearchableActivity.JARGON);
    }
    

注意:切勿从 onSearchRequested() 回调方法之外调用 startSearch() 方法。要在 Activity 中激活搜索对话框,请务必调用 onSearchRequested()。否则,系统不会调用 onSearchRequested(),并且会缺少自定义(如上例中添加的 appData)。

使用搜索微件

图 2. SearchView 微件作为操作栏中的“操作视图”。

在 Android 3.0 及更高版本中可以使用 SearchView 微件。如果您要针对 Android 3.0 开发应用并已决定使用搜索微件,我们建议您将搜索微件作为操作视图插入应用栏,而不是使用搜索对话框(也不是将搜索微件放置在 Activity 布局中)。例如,图 2 显示了应用栏中的搜索微件。

搜索微件提供的功能与搜索对话框相同。它可以在用户执行搜索时启动适当的 Activity,还可以提供搜索建议并执行语音搜索。如果您无法将搜索微件放在操作栏中,可以改为将搜索微件放在 Activity 布局中的某个位置。

注意:将搜索微件用作操作视图时,如果搜索微件不适合放在操作栏中,您仍可能需要支持使用搜索对话框。请参阅下面介绍如何同时使用微件和对话框的部分。

配置搜索微件

创建可搜索配置可搜索 Activity(如上所述)后,您需要为每个 SearchView 启用辅助搜索。为此,您可以调用 setSearchableInfo() 并向其传递表示可搜索配置的 SearchableInfo 对象。

您可以通过在 SearchManager 上调用 getSearchableInfo() 来获取对 SearchableInfo 的引用。

例如,如果您将 SearchView 用作应用栏中的操作视图,则应在 onCreateOptionsMenu() 回调期间启用微件:

Kotlin

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the options menu from XML
        val inflater = menuInflater
        inflater.inflate(R.menu.options_menu, menu)

        // Get the SearchView and set the searchable configuration
        val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
        (menu.findItem(R.id.menu_search).actionView as SearchView).apply {
            // Assumes current activity is the searchable activity
            setSearchableInfo(searchManager.getSearchableInfo(componentName))
            setIconifiedByDefault(false) // Do not iconify the widget; expand it by default
        }

        return true
    }
    

Java

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the options menu from XML
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.options_menu, menu);

        // Get the SearchView and set the searchable configuration
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
        // Assumes current activity is the searchable activity
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by default

        return true;
    }
    

这就是您所需的一切。搜索微件现已配置完毕,系统会将搜索查询传递给可搜索 Activity。您还可以为搜索微件启用搜索建议

注意:如果您要自行处理所有用户输入,则可以使用一些回调方法和事件监听器来执行此操作。如需了解详情,请参阅 SearchView 及其用于相应事件监听器的嵌套接口的参考文档。

如需详细了解操作栏中的操作视图,请参阅操作视图和操作提供程序

搜索微件的其他功能

SearchView 微件还提供了您可能需要的一些其他功能:

提交按钮
默认情况下,没有用于提交搜索查询的按钮,因此用户必须按键盘上的回车键来发起搜索操作。您可以通过调用 setSubmitButtonEnabled(true) 来添加一个“提交”按钮。
搜索建议的查询优化
启用搜索建议后,您通常希望用户直接选择一条建议,但他们也可能想要优化建议的搜索查询。您可以通过调用 setQueryRefinementEnabled(true) 在每条建议旁边添加一个按钮,用于将建议插入搜索框以供用户进行优化。
切换搜索框可见性的功能
默认情况下,搜索微件是“图标化”的微件,这意味着它只由搜索图标(放大镜)来表示,当用户轻触它时会展开以显示搜索框。如上所示,您可以通过调用 setIconifiedByDefault(false) 在默认情况下显示搜索框。您还可以通过调用 setIconified() 来切换搜索微件的外观。

SearchView 类中还有其他一些 API 可用于自定义搜索微件。不过,其中大多数 API 只有在您自行处理所有用户输入而不是使用 Android 系统传递搜索查询并显示搜索建议时才使用。

同时使用微件和对话框

如果您将搜索微件作为操作视图插入操作栏,并且在有空间的情况下(通过设置 android:showAsAction="ifRoom")让其显示在操作栏中,则搜索微件有可能不会显示为操作视图,而是相应的菜单项会显示在溢出菜单中。例如,当您的应用在较小的屏幕上运行时,操作栏中可能没有足够的空间,无法将搜索微件连同其他操作项或导航元素一起显示,因此相应的菜单项会显示在溢出菜单中。当放置在溢出菜单中时,该项的作用就像普通菜单项一样,不会显示操作视图(搜索微件)。

要处理这种情况,当用户从溢出菜单中选择您将搜索微件附加到的菜单项时,它应激活搜索对话框。为使它这样做,您必须实现 onOptionsItemSelected() 来处理“搜索”菜单项,并通过调用 onSearchRequested() 来打开搜索对话框。

如需详细了解操作栏中的各项如何工作以及如何处理这种情况,请参阅操作栏开发者指南。

添加语音搜索

您可以通过向可搜索配置添加 android:voiceSearchMode 属性来向搜索对话框或搜索微件添加语音搜索功能。这样会添加一个用于启动语音提示的语音搜索按钮。用户说完话后,系统会将转录的搜索查询发送到可搜索 Activity。

例如:

    <?xml version="1.0" encoding="utf-8"?>
    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/search_label"
        android:hint="@string/search_hint"
        android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" >
    </searchable>
    

要启用语音搜索,必须提供值 showVoiceSearchButton,而第二个值 launchRecognizer 指定语音搜索按钮应启动一个识别程序,用于将转录的文本返回到可搜索 Activity。

您可以提供其他属性来指定语音搜索行为,如预期的语言和返回的结果数量上限。如需详细了解可用的属性,请参阅可搜索配置参考。

注意:请仔细考虑语音搜索是否适合您的应用。使用语音搜索按钮执行的所有搜索会立即发送到可搜索 Activity,而用户没有机会检查转录的查询。应对语音识别进行充分测试,确保它理解用户可能会在您的应用内提交的各种查询。

添加搜索建议

图 3. 包含自定义搜索建议的搜索对话框的屏幕截图。

在 Android 系统的协助下,搜索对话框和搜索微件均可在用户输入内容时提供搜索建议。系统管理建议的列表,并在用户选择建议时处理相应的事件。

您可以提供两种类型的搜索建议:

近期查询搜索建议
这些建议就是用户以前在您的应用中用作搜索查询的字词。

请参阅添加近期查询建议

自定义搜索建议
这些是您通过自己的数据源提供的搜索建议,可帮助用户立即选择他们正在搜索的正确拼写或内容。图 3 显示了字典应用的自定义建议的示例 - 用户可以选择一条建议,以立即转到相应的定义。

请参阅添加自定义建议