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

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

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

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

Основы

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

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

Чтобы предоставить предложения по последним запросам, вам необходимо:

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

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

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

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

После отображения последних предложений по запросу может произойти следующее:

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

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

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

Поставщик контента, необходимый для последних предложений по запросам, — это реализация SearchRecentSuggestionsProvider . Этот класс делает всё за вас. Вам нужно просто написать конструктор класса, который выполняет одну строку кода.

Например, вот полная реализация поставщика контента для последних предложений по запросам:

Котлин

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

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

Ява

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

Котлин

const val MODE: Int = DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES

Ява

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() вашей активности:

Котлин

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

Ява

@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() . Например:

Котлин

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

Ява

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

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