Как добавить собственные подсказки при поиске

Попробуйте Compose
Jetpack Compose – это рекомендуемый набор инструментов для создания пользовательского интерфейса в Android. Узнайте, как добавить функцию поиска в Compose.

Вы можете предоставлять подсказки при поиске на основе недавних поисковых запросов в диалоговом окне поиска Android или виджете поиска. Например, если пользователь ввел запрос "щенки", то при повторном вводе этого запроса он появится в подсказках. На рисунке 1 показан пример диалогового окна поиска с подсказками недавних запросов.

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

Основные сведения

Рисунок 1. Скриншот диалогового окна поиска с подсказками недавних запросов.

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

Чтобы показывать пользователям недавние запросы, выполните следующие действия:

  • Реализуйте действие с возможностью поиска.
  • Создайте поставщика контента, который расширяет SearchRecentSuggestionsProvider, и объявите его в манифесте приложения.
  • Измените конфигурацию поиска, добавив информацию о поставщике контента, который предоставляет подсказки при поиске.
  • Сохраняйте запросы в поставщике контента при каждом поиске.

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

Когда система определяет, что в вашем действии есть возможность поиска и подсказки при поиске, при вводе запроса пользователем происходит следующее:

  1. Система берет текст поискового запроса (все, что пользователь начинает вводить) и выполняет запрос к поставщику контента, который содержит ваши подсказки.
  2. Поставщик контента возвращает объект Cursor, который указывает на все подсказки, соответствующие тексту поискового запроса.
  3. Система показывает список подсказок, предоставленных Cursor.

После того как появятся подсказки, может произойти следующее:

  • Если пользователь вводит другой символ или как-то изменяет запрос, предыдущие шаги повторяются и список подсказок обновляется.
  • Если пользователь выполняет поиск, подсказки игнорируются, а поиск передается в ваше действие с возможностью поиска с помощью обычного намерения ACTION_SEARCH.
  • Если пользователь выбирает подсказку, в ваше действие, поддерживающее поиск, передается намерение ACTION_SEARCH, в котором в качестве запроса используется текст подсказки.

Класс SearchRecentSuggestionsProvider, который вы расширяете для поставщика контента, автоматически выполняет действия, описанные выше, поэтому вам не нужно писать много кода.

Как создать поставщика контента

Поставщик контента, который нужен для подсказок на основе недавних запросов, – это реализация 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;

Объявите поставщика контента в манифесте приложения с той же строкой полномочий, которая используется в классе SearchRecentSuggestionsProvider и в конфигурации поиска. Пример:

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

Изменение конфигурации поиска

Чтобы настроить систему на использование вашего поставщика подсказок, добавьте атрибуты android:searchSuggestAuthority и android: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 должно быть полным именем поставщика контента, которое точно соответствует центру сертификации, используемому в поставщике контента, например "com.example.MySuggestionProvider" в предыдущих примерах.

Значение android:searchSuggestSelection должно быть вопросительным знаком, перед которым стоит пробел: " ?". Это плейсхолдер для аргумента выбора SQLite, который автоматически заменяется текстом запроса, введенным пользователем.

Сохранение запросов

Чтобы заполнить коллекцию недавних запросов, добавьте каждый запрос, полученный вашим действием с возможностью поиска, в SearchRecentSuggestionsProvider. Для этого создайте экземпляр SearchRecentSuggestions и вызывайте saveRecentQuery() каждый раз, когда ваше действие с возможностью поиска получает запрос. Например, вот как можно сохранить запрос в методе 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();

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