Dodawanie niestandardowych sugestii wyszukiwania

Wypróbuj Compose
Jetpack Compose to zalecany zestaw narzędzi do tworzenia interfejsu użytkownika na Androidzie. Dowiedz się, jak dodać funkcję wyszukiwania w Compose.

Możesz podawać sugestie wyszukiwania na podstawie ostatnich zapytań w oknie wyszukiwania Androida lub w widżecie wyszukiwania. Jeśli na przykład użytkownik wpisze „szczeniaki”, to gdy wpisze to samo zapytanie ponownie, pojawi się ono jako sugestia. Na ilustracji 1 widać przykład okna wyszukiwania z sugestiami ostatnich zapytań.

Zanim zaczniesz, zaimplementuj okno wyszukiwania lub widżet wyszukiwania do podstawowych wyszukiwań w aplikacji. Aby dowiedzieć się, jak to zrobić, przeczytaj artykuł Tworzenie interfejsu wyszukiwania.

Podstawy

Ilustracja 1. Zrzut ekranu okna wyszukiwania z sugestiami ostatnich zapytań.

Sugestie ostatnich zapytań to zapisane wyszukiwania. Gdy użytkownik wybierze sugestię, Twoja aktywność z możliwością wyszukiwania otrzyma intencję ACTION_SEARCH z sugestią jako zapytaniem, które Twoja aktywność z możliwością wyszukiwania już obsługuje.

Aby podawać sugestie ostatnich zapytań, musisz:

  • zaimplementować aktywność z możliwością wyszukiwania;
  • utworzyć dostawcę treści, który rozszerza SearchRecentSuggestionsProvider i zadeklarować go w pliku manifestu aplikacji;
  • zmodyfikować konfigurację z możliwością wyszukiwania, dodając informacje o dostawcy treści, który podaje sugestie wyszukiwania;
  • zapisywać zapytania u dostawcy treści za każdym razem, gdy zostanie wykonane wyszukiwanie.

Tak jak system Android wyświetla okno wyszukiwania, tak samo wyświetla sugestie wyszukiwania pod oknem lub widżetem wyszukiwania. Ty podajesz źródło, z którego system pobiera sugestie.

Gdy system stwierdzi, że Twoja aktywność umożliwia wyszukiwanie i podaje sugestie wyszukiwania, po wpisaniu zapytania przez użytkownika nastąpią te działania:

  1. System pobiera tekst zapytania – wszystko, co użytkownik zacznie wpisywać – i wysyła zapytanie do dostawcy treści, który zawiera Twoje sugestie.
  2. Dostawca treści zwraca Cursor który wskazuje wszystkie sugestie pasujące do tekstu zapytania.
  3. System wyświetla listę sugestii podanych przez Cursor.

Po wyświetleniu sugestii ostatnich zapytań mogą wystąpić te sytuacje:

  • Jeśli użytkownik naciśnie inny klawisz lub w jakikolwiek sposób zmieni zapytanie, poprzednie kroki zostaną powtórzone, a lista sugestii zostanie zaktualizowana.
  • Jeśli użytkownik wykona wyszukiwanie, sugestie zostaną zignorowane, a wyszukiwanie zostanie przekazane do Twojej aktywności z możliwością wyszukiwania za pomocą zwykłej ACTION_SEARCH intencji.
  • Jeśli użytkownik wybierze sugestię, do Twojej aktywności z możliwością wyszukiwania zostanie przekazana intencja ACTION_SEARCH z sugerowanym tekstem jako zapytaniem.

Klasa SearchRecentSuggestionsProvider, którą rozszerzasz w przypadku dostawcy treści, automatycznie wykonuje czynności opisane w poprzednich krokach, więc nie musisz pisać dużo kodu.

Tworzenie dostawcy treści

Dostawca treści, którego potrzebujesz do sugestii ostatnich zapytań, to implementacja klasy SearchRecentSuggestionsProvider. Ta klasa robi wszystko za Ciebie. Musisz tylko napisać konstruktor klasy, który wykonuje 1 wiersz kodu.

Oto na przykład pełna implementacja dostawcy treści do sugestii ostatnich zapytań:

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

Wywołanie setupSuggestions() przekazuje nazwę organu wyszukiwania i tryb bazy danych. Organ wyszukiwania może być dowolnym unikalnym ciągiem znaków, ale najlepszym rozwiązaniem jest użycie pełnej i jednoznacznej nazwy dostawcy treści, np. nazwy pakietu, a następnie nazwy klasy dostawcy. Na przykład: "com.example.MySuggestionProvider".

Tryb bazy danych musi zawierać DATABASE_MODE_QUERIES i opcjonalnie może zawierać DATABASE_MODE_2LINES, który dodaje kolumnę do tabeli sugestii, dzięki czemu możesz podać drugi wiersz tekstu z każdą sugestią. Jeśli chcesz podać 2 wiersze w każdej sugestii, zobacz ten przykład:

Kotlin

const val MODE: Int = DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES

Java

public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;

Zadeklaruj dostawcę treści w pliku manifestu aplikacji, używając tego samego ciągu znaków organu, który został użyty w klasie SearchRecentSuggestionsProvider i w konfiguracji z możliwością wyszukiwania. Przykład:

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

Modyfikowanie konfiguracji z możliwością wyszukiwania

Aby skonfigurować system tak, aby korzystał z Twojego dostawcy sugestii, dodaj android:searchSuggestAuthority i android:searchSuggestSelection do elementu <searchable> w pliku konfiguracji z możliwością wyszukiwania. Przykład:

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

Wartość atrybutu android:searchSuggestAuthority musi być pełną i jednoznaczną nazwą mechanizmu dostarczania treści, która dokładnie odpowiada organowi używanemu przez mechanizm dostarczania treści, np. "com.example.MySuggestionProvider" w poprzednich przykładach.

Wartość atrybutu android:searchSuggestSelection musi być pojedynczym znakiem zapytania poprzedzonym spacją: " ?". Jest to symbol zastępczy argumentu wyboru SQLite, który jest automatycznie zastępowany tekstem zapytania wpisanym przez użytkownika.

Zapisywanie zapytań

Aby wypełnić kolekcję ostatnich zapytań, dodaj każde zapytanie otrzymane przez Twoją aktywność z możliwością wyszukiwania do klasy SearchRecentSuggestionsProvider. Aby to zrobić, utwórz instancję klasy SearchRecentSuggestions i wywołuj metodę saveRecentQuery() za każdym razem, gdy Twoja aktywność z możliwością wyszukiwania otrzyma zapytanie. Oto na przykład, jak możesz zapisać zapytanie w metodzie onCreate() aktywności:

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

Konstruktor klasy SearchRecentSuggestionsProvider wymaga tego samego organu i trybu bazy danych, które zostały zadeklarowane przez dostawcę treści.

Metoda saveRecentQuery() przyjmuje jako pierwszy parametr ciąg zapytania, a jako drugi opcjonalnie ciąg znaków, który ma być uwzględniony jako drugi wiersz sugestii, lub wartość null. Drugi parametr jest używany tylko wtedy, gdy włączysz tryb 2-wierszowy dla sugestii wyszukiwania za pomocą DATABASE_MODE_2LINES. Jeśli włączysz tryb 2-wierszowy, tekst zapytania będzie pasował do drugiego wiersza, gdy system będzie szukać pasujących sugestii.

Czyszczenie danych sugestii

Aby chronić prywatność użytkownika, zawsze udostępniaj mu możliwość wyczyszczenia sugestii ostatnich zapytań. Aby wyczyścić historię zapytań, wywołaj metodę clearHistory(). Przykład:

Kotlin

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

Java

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

Wykonaj tę czynność, wybierając element menu „Wyczyść historię wyszukiwania”, element preferencji lub przycisk. Wyświetl okno potwierdzenia, aby sprawdzić, czy użytkownik chce usunąć historię wyszukiwania.