アプリ内に検索機能を提供するために、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>
検索アイコンにアクセスしやすくするには、/res/drawable
フォルダに ic_search.xml
ファイルを作成し、そのファイルに次のコードを含めます。
<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
をアプリバーに表示するには、アクティビティの onCreateOptionsMenu()
メソッドで XML メニュー リソース res/menu/options_menu.xml
をインフレートします。
Kotlin
override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.options_menu, menu) return true }
アプリを実行すると、次のような出力が生成されます。
SearchView
はアプリのアプリバーに表示されますが、機能しません。検索アイコンをタップすると、次のように表示されます。
SearchView
を機能させるには、SearchView
の動作を定義する必要があります。
検索構成を作成する
検索構成は SearchView
の動作を指定し、res/xml/searchable.xml
ファイルで定義されます。検索構成には、少なくとも、Android マニフェストの <application> 要素または <activity> 要素の android:label
属性と同じ値を持つ android:label
属性が含まれている必要があります。ただし、検索ボックスに何を入力するかをユーザーが把握できるように、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" />
アプリのマニフェスト ファイルで、res/xml/searchable.xml
ファイルを指す <meta-data>
要素を宣言します。SearchView
を表示する <activity>
で要素を宣言します。
<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()
メソッドで setSearchableInfo(SearchableInfo)
を呼び出して、検索構成を SearchView
に関連付けます。
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()
を呼び出すと、検索構成 XML ファイルから作成された SearchableInfo
オブジェクトを取得できます。検索設定が SearchView
に正しく関連付けられ、ユーザーがクエリを送信すると、SearchView
は ACTION_SEARCH
インテントでアクティビティを開始します。このインテントでフィルタして検索クエリを処理できるアクティビティが必要になります。
検索可能なアクティビティを作成する
検索可能なアクティビティは ACTION_SEARCH
インテントをフィルタし、データセットでクエリを検索します。検索可能なアクティビティを作成するには、任意のアクティビティを宣言して、ACTION_SEARCH
インテントをフィルタするようにします。
<activity android:name=".SearchResultsActivity" ... > ... <intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> ... </activity>
検索可能なアクティビティでは、onCreate()
メソッドで ACTION_SEARCH
インテントを確認して処理します。
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
に渡すことができます。ここで、クエリをアーキテクチャの他のレイヤで使用して、表示する検索結果を取得します。