Настройте интерфейс поиска

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

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

Добавьте SearchView на панель приложения

Чтобы добавить виджет SearchView на панель приложения, создайте в проекте файл с названием res/menu/options_menu.xml и добавьте в него следующий код: Этот код определяет, как создать элемент поиска, например, какой значок использовать и как назвать элемент. Атрибут collapseActionView позволяет элементу SearchView расширяться, чтобы занимать всю панель приложения, и сворачиваться обратно в обычный элемент панели приложения, когда он не используется. Поскольку на мобильных устройствах панель приложения имеет ограниченный размер, мы рекомендуем использовать атрибут collapsibleActionView.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/search"
        android:title="@string/search_title"
        android:icon="@drawable/ic_search"
        android:showAsAction="collapseActionView|ifRoom"
        android:actionViewClass="androidx.appcompat.widget.SearchView" />
</menu>

Если вы хотите, чтобы значок поиска был более заметным, создайте файл ic_search.xml в папке /res/drawable и добавьте в него следующий код:

<vector
    android:height="24dp"
    android:tint="#000000"
    android:viewportHeight="24"
    android:viewportWidth="24"
    android:width="24dp"
    xmlns:android="http://schemas.android.com/apk/res/android">
        <path android:fillColor="@android:color/white" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>

Чтобы показать SearchView на панели приложения, добавьте ресурс меню XML res/menu/options_menu.xml в метод onCreateOptionsMenu() своего класса activity:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.options_menu, menu)

    return true
}

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

Изображение, на котором показан пустой экран со значком поиска в верхней панели приложения.
Рисунок 1. Значок поиска на верхней панели приложения.

Значок SearchView появляется на панели приложения, но не работает. Если вы нажмете на значок поиска, то увидите примерно следующее:

Изображение, на котором показан режим поиска
Рисунок 2. SearchView в действии.

Чтобы SearchView работал, необходимо определить его SearchView поведение.

Как создать конфигурацию поиска

Конфигурация поиска определяет поведение SearchView и задается в файле res/xml/searchable.xml. Конфигурация поиска должна содержать как минимум атрибут android:label с тем же значением, что и у атрибута android:label элемента <application> или <activity> в манифесте Android. Однако мы также рекомендуем добавить атрибут android:hint, чтобы пользователь понимал, что нужно ввести в окно поиска.

<?xml version="1.0" encoding="utf-8"?>

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/app_name"
        android:hint="@string/search_hint" />

В файле манифеста приложения объявите элемент <meta-data>, который указывает на файл res/xml/searchable.xml. Объявите элемент в <activity>, в котором вы хотите показывать SearchView.

<activity
android:name=".SearchResultsActivity"
android:exported="false"
android:label="@string/title_activity_search_results"
android:launchMode="singleTop"
android:theme="@style/Theme.AppCompat.Light">
    <intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    <meta-data
        android:name="android.app.searchable"
        android:resource="@xml/searchable" />
</activity>

В созданном методе onCreateOptionsMenu() свяжите конфигурацию поиска с SearchView, вызвав setSearchableInfo(SearchableInfo):

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.options_menu, menu)

    val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
    val searchView = menu.findItem(R.id.search).actionView as SearchView
    val component = ComponentName(this, SearchResultsActivity::class.java)
    val searchableInfo = searchManager.getSearchableInfo(component)
    searchView.setSearchableInfo(searchableInfo)
    return true
}

Вызов getSearchableInfo() возвращает объект SearchableInfo, созданный на основе XML-файла конфигурации поиска. Когда конфигурация поиска правильно связана с вашим SearchView и пользователь отправляет запрос, SearchView запускает действие с намерением ACTION_SEARCH. Затем вам понадобится действие, которое может отфильтровать этот intent и обработать поисковый запрос.

Как создать действие, доступное для поиска

Действие с возможностью поиска фильтрует намерение ACTION_SEARCH и ищет запрос в наборе данных. Чтобы создать действие, по которому можно выполнять поиск, объявите действие, которое будет фильтровать намерение ACTION_SEARCH:

<activity android:name=".SearchResultsActivity" ... >
    ...
    <intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    ...
</activity>

В объекте activity, поддерживающем поиск, обработайте намерение ACTION_SEARCH, проверив его в методе onCreate().

Kotlin

class SearchResultsActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_search_results)
        handleIntent(intent)
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        handleIntent(intent)
    }

    private fun handleIntent(intent: Intent) {
        if (Intent.ACTION_SEARCH == intent.action) {
            val query = intent.getStringExtra(SearchManager.QUERY)
            Log.d("SEARCH", "Search query was: $query")
        }
    }
}

Теперь SearchView может принять запрос пользователя и запустить действие с намерением ACTION_SEARCH.

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