Android 3.0 以降、アプリで検索を提供するには、SearchView
ウィジェットをアプリバーの項目として使用することをおすすめします。SearchView
についてもアプリバーの他の項目と同じように表示方法を定義して、常に表示したり、スペースがある場合にのみ表示したりできます。または、折りたたみ可能なアクションとして定義すると、最初は SearchView
がアイコンとして表示され、ユーザーがアイコンをクリックするとアプリバー全体が検索フィールドになります。
注: このコースの後半では、SearchView
をサポートしていない Android 2.1(API レベル 7)を搭載したデバイスまで対象にして、下位互換性をアプリで実現する方法について紹介します。
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="android.widget.SearchView" /> </menu>
注: メニュー項目用の XML ファイルがすでにあれば、代わりにそのファイルに <item>
要素を追加することができます。
SearchView
をアプリバーに表示するには、アプリのアクティビティの onCreateOptionsMenu()
メソッド内に XML メニュー リソース(res/menu/options_menu.xml
)をインフレートします。
Kotlin
override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.options_menu, menu) return true }
Java
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.options_menu, menu); return true; }
ここでアプリを実行すると、SearchView
はアプリのアプリバーに表示されますが、まだ機能しません。これから、SearchView
がどのように動作するかを定義する必要があります。
検索可能性の設定を作成する
検索可能性の設定は、SearchView
の動作を res/xml/searchable.xml
ファイル内に定義するものです。検索可能性の設定に最小限必要なのは android:label
属性です。この属性の値は、Android マニフェスト内の <application> 要素または <activity> 要素の 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" />
アプリのマニフェスト ファイルでは、<meta-data>
要素を宣言し、res/xml/searchable.xml
ファイルを指すように設定して、アプリがどこを探せばよいかを伝えます。この要素は、SearchView
を表示する <activity>
内で宣言します。
<activity ... > ... <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) // Associate searchable configuration with the SearchView val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager (menu.findItem(R.id.search).actionView as SearchView).apply { setSearchableInfo(searchManager.getSearchableInfo(componentName)) } return true }
Java
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.options_menu, menu); // Associate searchable configuration with the SearchView SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView(); searchView.setSearchableInfo( searchManager.getSearchableInfo(getComponentName())); return true; }
getSearchableInfo()
を呼び出すと、検索可能性の設定の XML ファイルから作成される SearchableInfo
オブジェクトを取得できます。検索可能性の設定が SearchView
に正常に関連付けられると、SearchView
はユーザーからのクエリの送信時に、ACTION_SEARCH
インテントを持つアクティビティを開始します。ここで、このインテントをフィルタし、その検索クエリを処理するアクティビティが必要です。
検索可能なアクティビティを作成する
ユーザーが検索クエリを送信すると、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
インテントを確認し、処理します。
注: 検索可能なアクティビティがシングルトップ モード(android:launchMode="singleTop"
)で開始される場合、ACTION_SEARCH
インテントも onNewIntent()
メソッド内で処理します。シングルトップ モードでは、アクティビティのインスタンスは 1 つしか作成されず、そのアクティビティを開始する呼び出しがその後にあっても、新しいアクティビティがスタック上に作成されることはありません。毎回新しいアクティビティのインスタンスが作成されることなく、ユーザーが同じアクティビティから検索できるので、この開始モードは便利です。
Kotlin
class SearchResultsActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { ... handleIntent(intent) } override fun onNewIntent(intent: Intent) { ... handleIntent(intent) } private fun handleIntent(intent: Intent) { if (Intent.ACTION_SEARCH == intent.action) { val query = intent.getStringExtra(SearchManager.QUERY) //use the query to search your data somehow } } ... }
Java
public class SearchResultsActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { ... handleIntent(getIntent()); } @Override protected void onNewIntent(Intent intent) { ... handleIntent(intent); } private void handleIntent(Intent intent) { if (Intent.ACTION_SEARCH.equals(intent.getAction())) { String query = intent.getStringExtra(SearchManager.QUERY); //use the query to search your data somehow } } ... }
ここでアプリを実行すると、SearchView
はユーザーのクエリを受け付けて、ACTION_SEARCH
インテントを持つ検索可能なアクティビティを開始できます。この後は、クエリに返すデータを保存する方法と検索する方法を検討してください。