Создайте интерфейс поиска

Когда вы будете готовы добавить в свое приложение функцию поиска, Android поможет вам реализовать пользовательский интерфейс либо с помощью диалогового окна поиска, которое появляется в верхней части окна активности, либо с помощью виджета поиска, который вы можете вставить в свой макет. И диалоговое окно поиска, и виджет могут доставить поисковый запрос пользователя к определенному действию в вашем приложении. Таким образом, пользователь может инициировать поиск из любого действия, где доступно диалоговое окно поиска или виджет, а система запускает соответствующее действие для выполнения поиска и представления результатов.

Другие функции, доступные для диалогового окна поиска и виджета, включают:

  • Голосовой поиск
  • Поисковые предложения на основе недавних запросов
  • Поисковые предложения, соответствующие фактическим результатам в данных вашего приложения.

В этом документе показано, как настроить ваше приложение для предоставления интерфейса поиска, который помогает системе Android доставлять поисковые запросы с помощью диалогового окна поиска или виджета поиска.

Связанные ресурсы:

Основы

Прежде чем начать, решите, хотите ли вы реализовать свой интерфейс поиска с помощью диалогового окна поиска или виджета поиска. Они предоставляют одни и те же функции поиска, но немного по-разному:

  • Диалоговое окно поиска — это компонент пользовательского интерфейса, управляемый системой Android. При активации пользователем диалоговое окно поиска появляется в верхней части действия.

    Система Android контролирует все события в диалоге поиска. Когда пользователь отправляет запрос, система передает запрос действию, указанному вами для обработки поиска. Диалог также может предоставлять предложения по поиску, пока пользователь печатает.

  • Виджет поиска — это экземпляр SearchView , который вы можете разместить в любом месте макета. По умолчанию виджет поиска ведет себя как стандартный виджет EditText и ничего не делает, но вы можете настроить его так, чтобы система Android обрабатывала все входные события, перенаправляла запросы к соответствующему действию и предоставляла предложения по поиску — точно так же, как поиск диалог.

Когда пользователь выполняет поиск из диалогового окна поиска или виджета поиска, система создает Intent и сохраняет в нем пользовательский запрос. Затем система запускает действие, которое вы объявляете для обработки поиска — «действие с возможностью поиска» — и передает ему намерение. Чтобы настроить приложение для такого типа поиска с поддержкой, вам необходимо следующее:

  • Конфигурация поиска
    XML-файл, который настраивает некоторые параметры диалогового окна поиска или виджета. Он включает в себя настройки таких функций, как голосовой поиск, поисковые предложения и текст подсказки для поля поиска.
  • Поисковая деятельность
    Activity , которое получает поисковый запрос, выполняет поиск по вашим данным и отображает результаты поиска.
  • Интерфейс поиска, предоставляемый одним из следующих вариантов:
    • Диалог поиска
      По умолчанию диалог поиска скрыт. Он появляется в верхней части экрана, когда вы вызываете onSearchRequested() , когда пользователь нажимает кнопку «Поиск» .
    • SearchView
      Использование виджета поиска позволяет разместить окно поиска в любом месте вашей активности, в том числе в виде представления действий на панели приложения.

В оставшейся части этого документа показано, как создать конфигурацию поиска и активность поиска, а также как реализовать интерфейс поиска с диалоговым окном поиска или виджетом поиска.

Создайте конфигурацию с возможностью поиска

Первое, что вам понадобится, — это XML-файл, который называется конфигурацией поиска . Он настраивает определенные аспекты пользовательского интерфейса диалогового окна поиска или виджета и определяет поведение таких функций, как предложения и голосовой поиск. Этот файл традиционно называется searchable.xml и должен быть сохранен в каталоге проекта res/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 , который предоставляет строку подсказки в поле поиска, прежде чем пользователи введут запрос. Подсказка важна, поскольку она дает пользователям важные подсказки о том, что они могут искать.

Элемент <searchable> принимает несколько других атрибутов. Однако большинство атрибутов вам не понадобятся, пока вы не добавите такие функции, как поисковые предложения и голосовой поиск . Подробную информацию о файле конфигурации поиска см. в справочном документе по конфигурации поиска .

Создайте действие с возможностью поиска

Действие с возможностью поиска — это Activity в вашем приложении, которое выполняет поиск на основе строки запроса и представляет результаты поиска.

Когда пользователь выполняет поиск в диалоговом окне поиска или виджете, система запускает вашу активность поиска и доставляет ей поисковый запрос в Intent с действием ACTION_SEARCH . Ваша активность поиска извлекает запрос из дополнительного QUERY , затем выполняет поиск по вашим данным и представляет результаты.

Поскольку вы можете включить диалоговое окно поиска или виджет в любое другое действие в вашем приложении, система должна знать, какое действие является вашим действием, доступным для поиска, чтобы она могла правильно доставить поисковый запрос. Итак, сначала объявите свою активность поиска в файле манифеста Android.

Объявить действие, доступное для поиска

Если у вас его еще нет, создайте Activity , которое выполняет поиск и представляет результаты. Вам пока не нужно реализовывать функцию поиска — просто создайте активность, которую можно объявить в манифесте. Внутри элемента <activity> манифеста выполните следующие действия:

  1. Объявите действие для принятия намерения ACTION_SEARCH в элементе <intent-filter> .
  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:name со значением "android.app.searchable" и атрибут android:resource со ссылкой на файл конфигурации с возможностью поиска. В предыдущем примере это относится к файлу res/xml/searchable.xml .

Выполнить поиск

После того как вы объявите свою активность поиска в манифесте, выполните следующую процедуру, чтобы выполнить поиск в своей активности поиска:

  1. Получите запрос .
  2. Найдите свои данные .
  3. Представьте результаты .

Получить запрос

Когда пользователь выполняет поиск из диалогового окна поиска или виджета, система запускает вашу активность поиска и отправляет ей намерение ACTION_SEARCH . Это намерение содержит дополнительный поисковый запрос в строке QUERY . Проверьте это намерение при запуске действия и извлеките строку. Например, вот как вы можете получить поисковый запрос, когда начинается ваша активность поиска:

Котлин

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

Ява

@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 . В предыдущем примере запрос извлекается и передается локальному методу doMySearch() , где и выполняется фактическая операция поиска.

Поиск ваших данных

Процесс хранения и поиска ваших данных уникален для вашего приложения. Вы можете хранить и искать свои данные разными способами, и в этом документе не показано, как это сделать. Подумайте, как вы храните и осуществляете поиск данных, с точки зрения ваших потребностей и формата данных. Ниже приведены советы, которые вы можете применить:

  • Если ваши данные хранятся в базе данных SQLite на устройстве, выполнение полнотекстового поиска с использованием FTS3, а не запроса LIKE , может обеспечить более надежный поиск по текстовым данным и может дать результаты значительно быстрее. См. sqlite.org для получения информации о FTS3 и классе SQLiteDatabase для получения информации о SQLite на Android.
  • Если ваши данные хранятся в Интернете, то воспринимаемая эффективность поиска может быть ограничена подключением пользователя к данным. Возможно, вы захотите отображать индикатор прогресса до тех пор, пока поиск не вернется. См. android.net для получения справки по сетевым API и ProgressBar для получения информации о том, как отображать индикатор прогресса.

Представьте результаты

Независимо от того, где находятся ваши данные и как вы их ищете, мы рекомендуем вам возвращать результаты поиска в вашу активность поиска с помощью Adapter . Таким образом, вы можете представить все результаты поиска в RecyclerView . Если ваши данные получены из запроса к базе данных SQLite, вы можете применить свои результаты к RecyclerView с помощью CursorAdapter . Если ваши данные поступают в другом формате, вы можете создать расширение BaseAdapter .

Adapter связывает каждый элемент из набора данных с объектом View . Когда Adapter применяется к RecyclerView , каждая часть данных вставляется в список как отдельное представление. Adapter — это всего лишь интерфейс, поэтому необходимы такие реализации, как CursorAdapter — для привязки данных из Cursor . Если ни одна из существующих реализаций не работает для ваших данных, вы можете реализовать свою собственную из BaseAdapter .

Используйте диалог поиска

Диалоговое окно поиска представляет собой плавающее поле поиска в верхней части экрана со значком приложения слева. Диалоговое окно поиска может предоставлять предложения по поиску по мере ввода пользователем. Когда пользователь выполняет поиск, система отправляет поисковый запрос в действие с возможностью поиска, которое выполняет поиск.

По умолчанию диалоговое окно поиска всегда скрыто, пока пользователь не активирует его. Ваше приложение может активировать диалоговое окно поиска, вызвав onSearchRequested() . Однако этот метод не работает, пока вы не включите диалоговое окно поиска для действия.

Чтобы разрешить диалогу поиска выполнять поиск, укажите системе, какое действие, доступное для поиска, должно получать поисковые запросы из диалога поиска. Например, в предыдущем разделе о создании действия с возможностью поиска создается действие с возможностью поиска с именем SearchableActivity . Если вы хотите, чтобы отдельное действие, например с именем OtherActivity , отображало диалоговое окно поиска и доставляло поиск в SearchableActivity , объявите в манифесте, что SearchableActivity — это действие с возможностью поиска, которое будет использоваться для диалогового окна поиска в OtherActivity .

Чтобы объявить действие с возможностью поиска для диалогового окна поиска действия, добавьте элемент <meta-data> внутри элемента <activity> соответствующего действия. Элемент <meta-data> должен включать атрибут android:value , который определяет имя класса действия, доступного для поиска, и атрибут android:name со значением "android.app.default_searchable" .

Например, вот объявление как для действия с возможностью поиска, SearchableActivity , так и для другого действия, OtherActivity , которое использует SearchableActivity для выполнения поиска, выполняемого из его диалогового окна поиска:

<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> , чтобы объявить, какое действие с возможностью поиска использовать для поиска, это действие включает диалоговое окно поиска. Хотя пользователь находится в этом действии, метод onSearchRequested() активирует диалоговое окно поиска. Когда пользователь выполняет поиск, система запускает SearchableActivity и передает ему намерение ACTION_SEARCH .

Если вы хотите, чтобы каждое действие в вашем приложении предоставляло диалоговое окно поиска, вставьте предыдущий элемент <meta-data> в качестве дочернего элемента <application> вместо каждого <activity> . Таким образом, каждое действие наследует значение, предоставляет диалоговое окно поиска и доставляет поиск к одному и тому же действию, доступному для поиска. Если у вас есть несколько действий с возможностью поиска, вы можете переопределить действие с возможностью поиска по умолчанию, поместив другое объявление <meta-data> внутри отдельных действий.

Теперь, когда диалоговое окно поиска включено для ваших действий, ваше приложение готово выполнять поиск.

Вызов диалога поиска

Хотя на некоторых устройствах имеется специальная кнопка поиска, поведение кнопки может различаться на разных устройствах, а на многих устройствах кнопка поиска вообще не предусмотрена. Поэтому при использовании диалогового окна поиска вы должны предоставить кнопку поиска в своем пользовательском интерфейсе, которая активирует диалоговое окно поиска путем вызова onSearchRequested() .

Например, добавьте кнопку поиска в меню параметров или макет пользовательского интерфейса, который вызывает onSearchRequested() .

Вы также можете включить функцию «ввод текста для поиска», которая активирует диалоговое окно поиска, когда пользователь начинает печатать на клавиатуре. Нажатия клавиш вставляются в диалог поиска. Вы можете включить поиск по типу в своей активности, вызвав setDefaultKeyMode — или DEFAULT_KEYS_SEARCH_LOCAL — во время метода onCreate() вашей активности.

Влияние диалогового окна поиска на жизненный цикл вашей деятельности

Диалог поиска — это Dialog , который плавает в верхней части экрана. Это не приводит к каким-либо изменениям в стеке действий, поэтому при появлении диалогового окна поиска никакие методы жизненного цикла, такие как onPause() не вызываются. Ваша деятельность теряет фокус ввода, поскольку фокус ввода передается диалоговому окну поиска.

Если вы хотите получать уведомление при активации диалогового окна поиска, переопределите метод onSearchRequested() . Когда система вызывает этот метод, это указывает на то, что ваше действие теряет фокус ввода в диалоговом окне поиска, поэтому вы можете выполнить любую работу, соответствующую событию, например приостановить игру. Если вы не передаете данные контекста поиска (обсуждаемые в другом разделе этого документа), завершите метод, вызвав реализацию суперкласса:

Котлин

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

Ява

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

Если пользователь отменяет поиск, нажав кнопку «Назад», диалоговое окно поиска закрывается, и действие восстанавливает фокус ввода. Вы можете зарегистрироваться для получения уведомлений при закрытии диалогового окна поиска с помощью setOnDismissListener() , setOnCancelListener() или обоих. Вам нужно только зарегистрировать OnDismissListener , поскольку он вызывается каждый раз, когда закрывается диалог поиска. OnCancelListener относится только к событиям, в которых пользователь явно выходит из диалогового окна поиска, поэтому он не вызывается при выполнении поиска. После выполнения поиска диалоговое окно поиска автоматически исчезает.

Если текущее действие не является доступным для поиска, то обычные события жизненного цикла действия запускаются, когда пользователь выполняет поиск — текущее действие получает onPause() , как описано в разделе «Введение в действия» . Однако если текущая активность доступна для поиска, происходит одно из двух:

  • По умолчанию действие с возможностью поиска получает намерение ACTION_SEARCH с вызовом onCreate() , и новый экземпляр действия переносится на вершину стека действий. Теперь в стеке действий есть два экземпляра вашего действия с возможностью поиска, поэтому нажатие кнопки «Назад» возвращает вас к предыдущему экземпляру действия с возможностью поиска, а не выходит из действия с возможностью поиска.
  • Если вы установите android:launchMode значение "singleTop" , то действие с возможностью поиска получает намерение ACTION_SEARCH с вызовом onNewIntent(Intent) , передавая новое намерение ACTION_SEARCH . Например, вот как можно поступить в этом случае, когда режим запуска действия с возможностью поиска — "singleTop" :

    Котлин

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

    Ява

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.search);
        handleIntent(getIntent());
    }
    
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(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);
        }
    }
    

    По сравнению с примером кода в разделе о выполнении поиска , весь код для обработки намерения поиска теперь находится в методе handleIntent() , так что его могут выполнить как onCreate() , так и onNewIntent() .

    Когда система вызывает onNewIntent(Intent) действие не перезапускается, поэтому метод getIntent() возвращает то же намерение, которое получено с помощью onCreate() . Вот почему вы должны вызывать setIntent(Intent) внутри onNewIntent(Intent) : чтобы намерение, сохраненное действием, обновлялось в случае, если вы вызовете getIntent() в будущем.

Второй сценарий с использованием режима запуска "singleTop" обычно предпочтительнее, поскольку после завершения поиска пользователь может выполнить дополнительные поисковые запросы, а вы не хотите, чтобы ваше приложение создавало несколько экземпляров действия с возможностью поиска. Мы рекомендуем вам установить для активности поиска режим запуска "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>

Передача данных контекста поиска

В некоторых случаях вы можете внести необходимые уточнения в поисковый запрос внутри действия поиска для каждого выполненного поиска. Однако если вы хотите уточнить критерии поиска на основе активности, в рамках которой пользователь выполняет поиск, вы можете предоставить дополнительные данные в намерении, которое система отправляет в вашу активность поиска. Вы можете передать дополнительные данные в APP_DATA Bundle , который включен в намерение ACTION_SEARCH .

Чтобы передать данные такого типа в действие с возможностью поиска, переопределите метод onSearchRequested() для действия, из которого пользователь может выполнять поиск, создайте Bundle с дополнительными данными и вызовите startSearch() чтобы активировать диалоговое окно поиска. Например:

Котлин

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

Ява

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

Возврат true означает, что вы успешно обработали это событие обратного вызова и вызвали startSearch() чтобы активировать диалоговое окно поиска. После того как пользователь отправляет запрос, он доставляется в вашу активность поиска вместе с добавляемыми вами данными. Вы можете извлечь дополнительные данные из Bundle APP_DATA для уточнения поиска, как показано в следующем примере:

Котлин

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

Ява

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

Используйте виджет поиска

Изображение, показывающее вид поиска в верхней панели приложения.

Рис. 1. Виджет SearchView в виде представления действий на панели приложения.

Виджет поиска предоставляет те же функции, что и диалоговое окно поиска. Он запускает соответствующее действие, когда пользователь выполняет поиск, и может предлагать поисковые предложения и выполнять голосовой поиск. Если у вас нет возможности разместить виджет поиска на панели приложения, вы можете вместо этого разместить виджет поиска где-нибудь в макете действий.

Настройте виджет поиска

После создания конфигурации поиска и действия с возможностью поиска включите поиск с поддержкой для каждого SearchView , вызвав setSearchableInfo() и передав ему объект SearchableInfo , который представляет вашу конфигурацию с возможностью поиска.

Вы можете получить ссылку на SearchableInfo , вызвав getSearchableInfo() в SearchManager .

Например, если вы используете SearchView в качестве представления действий на панели приложения, включите виджет во время обратного вызова onCreateOptionsMenu() , как показано в следующем примере:

Котлин

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) // Don't iconify the widget. Expand it by default.
    }

    return true
}

Ява

@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); // Don't iconify the widget. Expand it by default.

    return true;
}

Виджет поиска теперь настроен, и система доставляет поисковые запросы к вашей активности поиска. Вы также можете включить поисковые предложения для виджета поиска.

Дополнительные сведения о представлениях действий на панели приложения см. в разделе Использование представлений действий и поставщиков действий .

Другие функции виджета поиска

Виджет SearchView предоставляет несколько дополнительных функций, которые могут вам понадобиться:

Кнопка отправки
По умолчанию кнопка для отправки поискового запроса отсутствует, поэтому пользователю необходимо нажать клавишу Return на клавиатуре, чтобы начать поиск. Вы можете добавить кнопку «Отправить», вызвав setSubmitButtonEnabled(true) .
Уточнение запроса для поисковых предложений
Когда вы включаете поисковые предложения, вы обычно ожидаете, что пользователи выберут предложение, но они также могут захотеть уточнить предлагаемый поисковый запрос. Вы можете добавить кнопку рядом с каждым предложением, которая вставляет предложение в поле поиска для уточнения пользователем, вызвав setQueryRefinementEnabled(true) .
Возможность переключать видимость окна поиска.
По умолчанию виджет поиска является «значком», то есть он представлен только значком поиска — увеличительным стеклом. Он расширяется и показывает окно поиска, когда пользователь нажимает на значок. Как показано в предыдущем примере, вы можете отобразить поле поиска по умолчанию, вызвав setIconifiedByDefault(false) . Вы также можете переключить внешний вид виджета поиска, вызвав setIconified() .

В классе SearchView есть несколько других API, которые позволяют настраивать виджет поиска. Однако большинство из них используются только тогда, когда вы самостоятельно обрабатываете все вводимые пользователем данные, а не используете систему Android для доставки поисковых запросов и отображения поисковых предложений.

Используйте и виджет, и диалоговое окно.

Если вы вставите виджет поиска в панель приложения в качестве представления действий и включите его отображение на панели приложения, если есть место, установив android:showAsAction="ifRoom" — тогда виджет поиска может не отображаться в виде представления действий. Вместо этого пункт меню может появиться в дополнительном меню. Например, когда ваше приложение работает на маленьком экране, на панели приложения может не хватить места для отображения виджета поиска вместе с другими элементами действий или элементами навигации, поэтому вместо этого элемент меню отображается в меню переполнения. При размещении в дополнительном меню элемент работает как обычный элемент меню и не отображает представление действий, то есть виджет поиска.

Чтобы справиться с этой ситуацией, пункт меню, к которому вы прикрепляете виджет поиска, должен активировать диалоговое окно поиска, когда пользователь выбирает его из дополнительного меню. Чтобы это произошло, реализуйте onOptionsItemSelected() для обработки пункта меню «Поиск» и откройте диалоговое окно поиска, вызвав onSearchRequested() .

Дополнительные сведения о том, как работают элементы на панели приложения и как справиться с этой ситуацией, см. в разделе Добавление панели приложения .

Добавить голосовой поиск

Вы можете добавить функцию голосового поиска в диалоговое окно поиска или виджет, добавив атрибут android:voiceSearchMode в свою конфигурацию поиска. Это добавляет кнопку голосового поиска, которая запускает голосовую подсказку. Когда пользователь заканчивает говорить, расшифрованный поисковый запрос отправляется в вашу активность поиска.

Это показано в следующем примере:

<?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 , указывает, что кнопка голосового поиска должна запускать распознаватель , который возвращает расшифрованный текст в действие с возможностью поиска.

Вы можете предоставить дополнительные атрибуты, чтобы указать поведение голосового поиска, например ожидаемый язык и максимальное количество возвращаемых результатов. Дополнительную информацию о доступных атрибутах см. в справочнике по конфигурации поиска .

Добавить поисковые предложения

И диалоговое окно поиска, и виджет поиска могут предлагать варианты поиска по мере ввода пользователем текста при помощи системы Android. Система управляет списком предложений и обрабатывает событие, когда пользователь выбирает предложение.

Вы можете предоставить два вида поисковых предложений:

Недавние предложения по поиску по запросу
Эти предложения представляют собой слова, которые пользователь ранее использовал в качестве поисковых запросов в вашем приложении. Дополнительную информацию см. в разделе Добавление пользовательских поисковых предложений .
Предложения пользовательского поиска
Это предложения по поиску, которые вы предоставляете из собственного источника данных, чтобы помочь пользователям немедленно выбрать правильное написание или элемент, который они ищут. Дополнительную информацию см. в разделе Добавление пользовательских поисковых предложений .