検索インターフェースの作成

アプリに検索機能を追加する準備ができたら、Android のサポートを通じて、アクティビティ ウィンドウの一番上に表示される検索ダイアログ、またはレイアウトに挿入可能な検索ウィジェットを使用したユーザー インターフェースを実装することができます。検索ダイアログと検索ウィジェットのどちらでも、ユーザーの検索クエリをアプリの特定のアクティビティに渡すことができます。このように、ユーザーは検索ダイアログまたは検索ウィジェットを使用可能なアクティビティから検索を開始できます。一方システムは、適切なアクティビティを開始して検索を実行し、検索結果を表示します。

検索ダイアログと検索ウィジェットでは以下の機能も使用できます。

  • 音声検索
  • 最近のクエリに基づく検索候補
  • 実際の検索結果と一致する、アプリデータ内の検索候補

このガイドでは、検索クエリの入力のために Android システムがサポートしている検索インターフェースを、検索ダイアログまたは検索ウィジェットを使用して表示するようにアプリを設定する方法について説明します。

関連資料:

基本

図 1. アプリの検索ダイアログのスクリーンショット

まず、検索ダイアログと検索ウィジェットのどちらを使用して検索インターフェースを実装するかを決める必要があります。どちらも同じ検索機能を提供しますが、その方法が少し異なります。

  • 検索ダイアログは、Android システムによって制御される UI コンポーネントです。ユーザーが検索ダイアログを有効にすると、図 1 に示すように、アクティビティの一番上に表示されます。

    検索ダイアログ内のイベントはすべて、Android システムが制御します。ユーザーがクエリを送信すると、指定したアクティビティにクエリが渡され、検索が処理されます。検索ダイアログには、ユーザーが入力しているときにも検索候補を表示できます。

  • 検索ウィジェットSearchView のインスタンスで、レイアウト内のどこにでも配置できます。デフォルトでは、検索ウィジェットは標準の EditText ウィジェットのように動作し、何も実行しませんが、Android システムがすべての入力イベントを処理し、クエリを適切なアクティビティに提供して、(検索ダイアログと同じように)検索候補を表示するように設定できます。

    注: 必要に応じて、各種のコールバック メソッドやリスナーを使用して、すべてのユーザー入力を検索ウィジェットに渡して自分で処理することもできます。ただしこのドキュメントでは、検索ウィジェットをシステムと統合して、Android がサポートする検索の実装を実現する方法について重点的に説明します。ユーザー入力をすべて自分で処理する場合は、SearchView とそのネストされたインターフェースのリファレンス ドキュメントをご覧ください。

ユーザーが検索ダイアログまたは検索ウィジェットから検索を実行すると、システムが Intent を作成して、その中にユーザークエリを格納します。さらに、検索の処理用に宣言したアクティビティ(「検索可能アクティビティ」)を開始し、そのアクティビティをインテントに渡します。このような Android がサポートする検索を行えるようにアプリを設定するには、以下のものが必要です。

  • 検索可能構成

    検索ダイアログまたは検索ウィジェットの一部の設定を行う XML ファイル。音声検索、検索候補、検索ボックスに表示するヒントのテキストなどの機能の設定がこのファイルに格納されます。

  • 検索可能アクティビティ

    検索クエリを受け取ってデータを検索し、検索結果を表示する Activity

  • 検索インターフェース(次のいずれかで提供)
    • 検索ダイアログ

      検索ダイアログはデフォルトでは表示されませんが、onSearchRequested() を呼び出したとき(ユーザーが検索ボタンを押したとき)に画面の一番上に表示されます。

    • SearchView ウィジェット

      検索ウィジェットを使用すると、アクティビティ内の任意の場所に検索ボックスを配置できます。通常は、検索ウィジェットをアクティビティ レイアウト内に配置する代わりに、アプリバー内のアクション ビューとして SearchView を使用する必要があります。

以下では、検索可能構成と検索可能アクティビティを作成し、検索ダイアログまたは検索ウィジェットを使用して検索インターフェースを実装する方法について説明します。

検索可能構成の作成

まず、検索可能構成と呼ばれる XML ファイルを作成する必要があります。このファイルでは、検索ダイアログまたは検索ウィジェットの特定の UI 要素を構成し、候補や音声検索などの機能の動作を定義します。このファイルには以前から searchable.xml という名前が使用されています。また、このファイルは res/xml/ プロジェクト ディレクトリに保存する必要があります。

注: システムはこのファイルを使用して SearchableInfo オブジェクトをインスタンス化しますが、このオブジェクトを実行時に自分で作成することはできません。検索可能構成は XML で宣言する必要があります。

検索可能構成ファイルでは、ルートノードとして <searchable> 要素を含め、1 つ以上の属性を指定する必要があります。次に例を示します。

    <?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" >
    </searchable>
    

android:label 属性は唯一の必須属性です。この属性は文字列リソース(アプリ名を指定する必要があります)を指します。このラベルは実際には、クイック検索ボックスの検索候補を有効にするまでユーザーに表示されません。検索候補を有効にすると、システム設定の検索対象のリストにこのラベルが表示されます。

android:hint 属性は必須ではありませんが、常に指定することをおすすめします。そうすることで、ユーザーがクエリを入力する前に、検索ボックスにヒントの文字列が表示されます。ヒントは重要です。ユーザーは自分が検索できるものについて、ヒントから重要な手がかりを得ることができます。

ヒント: 他の Android アプリとの間の整合性を保つために、android:hint の文字列は「<content-or-product> を検索」の形式にする必要があります(例: 「曲とアーティストを検索」、「YouTube を検索」)。

<searchable> 要素で指定できる属性は他にもいくつかあります。ただし、検索候補音声検索などの機能を追加するまでは、ほとんどの属性は必要ありません。検索可能構成ファイルについて詳しくは、検索可能構成のリファレンス ドキュメントをご覧ください。

検索可能アクティビティの作成

検索可能アクティビティは、クエリ文字列に基づいて検索を実行して検索結果を表示するアプリの Activity です。

ユーザーが検索ダイアログまたは検索ウィジェットで検索を実行すると、システムが検索可能アクティビティを開始し、ACTION_SEARCH アクションを含む Intent でそのアクティビティに検索クエリを渡します。検索可能アクティビティは、インテントの QUERY エクストラからクエリを取得し、その後でデータを検索して結果を表示します。

検索ダイアログまたは検索ウィジェットはアプリの他のどのアクティビティにも含めることができるため、システムは検索クエリを適切に渡すことができるよう、どのアクティビティが検索可能アクティビティかを認識している必要があります。そのため、Android マニフェスト ファイルで検索可能アクティビティを最初に宣言する必要があります。

検索可能アクティビティの宣言

検索を実行して結果を表示する Activity を作成します(まだ作成していない場合)。まだ検索機能を実装する必要はありません。ここでは、マニフェストで宣言可能なアクティビティを作成するだけです。マニフェストの <activity> 要素内で以下を行います。

  1. <intent-filter> 要素で、ACTION_SEARCH インテントを受け入れることができるアクティビティを宣言します。
  2. <meta-data> 要素で、使用する検索可能構成を指定します。

例:

    <application ... >
        <activity android:name=".SearchableActivity" >
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <meta-data android:name="android.app.searchable"
                       android:resource="@xml/searchable"/>
        </activity>
        ...
    </application>
    

<meta-data> 要素には、"android.app.searchable" という値が設定された android:name 属性と、検索可能構成ファイルへの参照(この例では res/xml/searchable.xml ファイルを参照しています)が設定された android:resource 属性を含める必要があります。

注: <intent-filter> では、DEFAULT 値が設定された <category> は必要ありません(通常は <activity> 要素で設定します)。これは、システムがコンポーネント名を使用して、検索可能アクティビティに明示的に ACTION_SEARCH インテントを渡すためです。

検索の実行

マニフェストで検索可能アクティビティを宣言したら、検索可能アクティビティで検索を実行します。検索の実行は、次の 3 つのステップで構成されます。

  1. クエリの受信
  2. データの検索
  3. 結果の表示

従来どおり、検索結果は ListView に表示する必要があります。そのため、検索可能アクティビティで ListActivity を拡張することをおすすめします。このアクティビティには 1 つの ListView が設定されたデフォルトのレイアウトが含まれており、ListView を操作するための便利なメソッドがいくつか用意されています。

クエリの受信

ユーザーが検索ダイアログまたは検索ウィジェットから検索を実行すると、システムが検索可能アクティビティを開始して、そのアクティビティに ACTION_SEARCH インテントを送信します。このインテントは、QUERY 文字列エクストラで検索クエリを伝送します。アクティビティが開始され、文字列を抽出するときにこのインテントをチェックする必要があります。以下に、検索可能アクティビティの開始時に検索クエリを取得する方法の例を示します。

Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.search)

        // Verify the action and get the query
        if (Intent.ACTION_SEARCH == intent.action) {
            intent.getStringExtra(SearchManager.QUERY)?.also { query ->
                doMySearch(query)
            }
        }
    }
    

Java

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.search);

        // Get the intent, verify the action and get the query
        Intent intent = getIntent();
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
          String query = intent.getStringExtra(SearchManager.QUERY);
          doMySearch(query);
        }
    }
    

ACTION_SEARCH インテントには必ず QUERY 文字列が含まれています。この例では、クエリが取得され、ローカルの doMySearch() メソッドに渡されています。実際の検索処理はこのメソッドで行われます。

データの検索

データの保存と検索は、アプリに固有のプロセスです。データの保存と検索はさまざまな方法で行うことができますが、このガイドではその方法については説明しません。データの保存と検索を行う場合、必要なデータとデータ形式について慎重に検討する必要があります。ここでは、データの保存と検索に関するヒントをいくつか紹介します。

  • デバイス上の SQLite データベースにデータが保存されている場合、(LIKE クエリではなく FTS3 を使用して)全文検索を実行することで、すべてのテキストデータに対する堅牢な検索を実行できるうえ、検索結果の作成時間を大幅に短縮できます。FTS3 について詳しくは、sqlite.org をご覧ください。また、Android での SQLite の使用方法については、SQLiteDatabase クラスをご覧ください。
  • データがオンラインに保存されている場合、ユーザーのデータ接続によって検索パフォーマンスが抑制されることがあります。そのため、検索結果が返ってくるまで進行状況ホイールを表示することをおすすめします。ネットワーク API のリファレンスについては android.net を、進行状況ホイールの表示方法については進行状況ダイアログの作成をご覧ください。

結果の表示

データの保存場所や検索方法に関係なく、検索結果を検索可能アクティビティに返す際には Adapter を使用することをおすすめします。これにより、すべての検索結果を ListView に簡単に表示することができます。SQLite データベース クエリでデータを取得した場合は、CursorAdapter を使用して ListView に検索結果を適用できます。異なる形式のデータを取得した場合は、BaseAdapter の拡張機能を作成できます。

Adapter は、各アイテムをデータセットから View オブジェクトにバインドします。AdapterListView に適用されると、各データが個々のビューとしてリストに挿入されます。Adapter は単なるインターフェースであるため、(Cursor からデータをバインドするために)CursorAdapter などの実装が必要になります。既存のどの実装もデータに合わない場合は、BaseAdapter から独自の実装を作成できます。

検索可能アクティビティで ListActivity を拡張する場合は、setListAdapter() を呼び出して、データにバインドされている Adapter を渡すことができます。これにより、すべての検索結果がアクティビティの ListView に挿入されます。

検索結果をリストで表示する方法については、ListActivity のドキュメントをご覧ください。

検索ダイアログの使用

検索ダイアログは、左側にアプリのアイコンが付いたフローティング検索ボックスで、画面の一番上に表示されます。検索ダイアログでは、ユーザーが入力しているときに検索候補を表示できます。ユーザーが検索を実行すると、検索を実行する検索可能アクティビティに検索クエリが送信されます。ただし、Android 3.0 が搭載されているデバイス向けのアプリを開発する場合は、検索ウィジェットを使用することを検討してください(検索ウィジェットの使用をご覧ください)。

検索ダイアログはデフォルトでは、ユーザーが有効化するまで非表示になっています。アプリで検索ダイアログを有効にするには、onSearchRequested() を呼び出します。ただし、アクティビティの検索ダイアログを有効にするまでこのメソッドは機能しません。

検索ダイアログを有効にするには、検索を実行するために検索可能アクティビティで検索ダイアログから検索クエリを受け取ることをシステムに示す必要があります。たとえば、前の検索可能アクティビティの作成セクションでは、SearchableActivity という名前の検索可能アクティビティを作成しました。OtherActivity という名前の別のアクティビティが必要な場合、検索ダイアログを表示し、検索クエリを SearchableActivity に渡すためには、SearchableActivityOtherActivity の検索ダイアログで使用する検索可能アクティビティであることをマニフェストで宣言する必要があります。

アクティビティの検索ダイアログ用の検索可能アクティビティを宣言するには、それぞれのアクティビティの <activity> 要素内に <meta-data> 要素を追加します。<meta-data> 要素には、検索可能アクティビティのクラス名を指定する android:value 属性と、"android.app.default_searchable" という値が設定された android:name 属性を含める必要があります。

以下の例では、検索可能アクティビティ SearchableActivity と、検索ダイアログから実行された検索を処理するために を使用するもう 1 つのアクティビティ OtherActivity を宣言しています。

    <application ... >
        <!-- this is the searchable activity; it performs searches -->
        <activity android:name=".SearchableActivity" >
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <meta-data android:name="android.app.searchable"
                       android:resource="@xml/searchable"/>
        </activity>

        <!-- this activity enables the search dialog to initiate searches
             in the SearchableActivity -->
        <activity android:name=".OtherActivity" ... >
            <!-- enable the search dialog to send searches to SearchableActivity -->
            <meta-data android:name="android.app.default_searchable"
                       android:value=".SearchableActivity" />
        </activity>
        ...
    </application>
    

これで、<meta-data> 要素が OtherActivity に追加され、検索に使用する検索可能アクティビティが宣言されたため、アクティビティで検索ダイアログが有効化されました。ユーザーがこのアクティビティを実行している間、onSearchRequested() メソッドによって検索ダイアログが有効化されます。ユーザーが検索を実行すると、システムが SearchableActivity を開始して、そのアクティビティに ACTION_SEARCH インテントを渡します。

注: 検索可能アクティビティ自体がデフォルトで検索ダイアログを表示するため、この宣言を SearchableActivity に追加する必要はありません。

アプリのすべてのアクティビティで検索ダイアログを表示する場合は、上述の <meta-data> 要素を各 <activity> ではなく <application> 要素の子として挿入します。これにより、すべてのアクティビティがこの値を継承し、検索ダイアログを表示して、同じ検索可能アクティビティに検索クエリを渡します(検索可能アクティビティが複数ある場合、アクティビティごとに別々の <meta-data> を宣言することで、デフォルトの検索可能アクティビティをオーバーライドできます)。

これで、アクティビティの検索ダイアログが有効化されたので、アプリで検索を実行できるようになりました。

検索ダイアログの呼び出し

一部のデバイスには専用の検索ボタンが用意されていますが、ボタンの動作はデバイスごとに異なります。また、多くのデバイスには検索ボタンが用意されていません。そのため、検索ダイアログを使用する場合は、onSearchRequested() を呼び出して検索ダイアログを有効化する検索ボタンを UI に用意する必要があります

たとえば、onSearchRequested() を呼び出す検索ボタンをオプション メニューまたは UI レイアウトに追加する必要があります。また、Android システムや他のアプリとの整合性を保つために、Action Bar Icon Pack から入手可能な Android 検索アイコンのラベルをボタンに付ける必要があります。

注: アプリでアプリバーを使用する場合は、検索インターフェースに検索ダイアログを使用しないでください。代わりに、アプリバー内で折りたたみ可能なビューとして検索ウィジェットを使用します。

また、「キーワードを入力して検索」機能を有効にすることができます。この機能は、ユーザーがキーボードで入力を開始したときに検索ダイアログを有効化します(キー入力が検索ダイアログに挿入されます)。アクティビティで「キーワードを入力して検索」機能を有効にするには、アクティビティの onCreate() メソッドで setDefaultKeyModeDEFAULT_KEYS_SEARCH_LOCAL)を呼び出します。

検索ダイアログがアクティビティのライフサイクルに及ぼす影響

検索ダイアログは、画面の一番上に表示されるフローティング Dialog です。検索ダイアログが表示されてもアクティビティ スタックに変化は生じないため、ライフサイクル メソッド(onPause() など)は呼び出されません。入力フォーカスが検索ダイアログに移るため、アクティビティから入力フォーカスが失われるだけです。

検索ダイアログが有効化されたときに通知を受け取りたい場合は、onSearchRequested() メソッドをオーバーライドします。システムがこのメソッドを呼び出したということは、入力フォーカスがアクティビティから失われ、検索ダイアログに移ったことを示すため、イベントに適した処理(ゲームの一時停止など)を実行できなくなります。検索コンテキスト データを渡す(後述)のでなければ、スーパークラスの実装を呼び出してこのメソッドを終了する必要があります。次に例を示します。

Kotlin

    override fun onSearchRequested(): Boolean {
        pauseSomeStuff()
        return super.onSearchRequested()
    }
    

Java

    @Override
    public boolean onSearchRequested() {
        pauseSomeStuff();
        return super.onSearchRequested();
    }
    

ユーザーが戻るボタンを押して検索をキャンセルすると、検索ダイアログが閉じて、入力フォーカスがアクティビティに戻ります。検索ダイアログが閉じたときに通知を受け取るように登録するには、setOnDismissListener() または setOnCancelListener()(あるいはその両方)を使用します。OnDismissListener は検索ダイアログが閉じるたびに呼び出されるため、このリスナー以外は登録する必要がありません。OnCancelListener は、ユーザーが検索ダイアログを明示的に終了したイベントにのみ関連するため、検索の実行時には呼び出されません(このリスナーが呼び出された場合、検索ダイアログは当然非表示になります)。

現在のアクティビティが検索可能アクティビティでない場合にユーザーが検索を実行すると、通常のアクティビティのライフサイクル イベントがトリガーされます(アクティビティのドキュメントで説明されているとおり、現在のアクティビティが onPause() などを受け取ります)。ただし、現在のアクティビティが検索可能アクティビティの場合は、次の 2 つのうちのどちらかが行われます。

  1. デフォルトでは、検索可能アクティビティが ACTION_SEARCH インテントを受け取って onCreate() を呼び出します。また、アクティビティの新しいインスタンスがアクティビティ スタックの一番上に追加されます。これで、検索可能アクティビティのインスタンスがアクティビティ スタック内に 2 つ存在する状態になります(そのため、戻るボタンを押すと、検索可能アクティビティが終了するのではなく、検索可能アクティビティの前のインスタンスに戻ります)。
  2. android:launchMode"singleTop" に設定すると、検索可能アクティビティが ACTION_SEARCH インテントを受け取って onNewIntent(Intent) を呼び出し、新しい ACTION_SEARCH インテントを渡します。以下に、この処理方法の例を示します。この場合の検索可能アクティビティの起動モードは "singleTop" です。

    Kotlin

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.search)
            handleIntent(intent)
        }
    
        override fun onNewIntent(intent: Intent) {
            setIntent(intent)
            handleIntent(intent)
        }
    
        private fun handleIntent(intent: Intent) {
            if (Intent.ACTION_SEARCH == intent.action) {
                intent.getStringExtra(SearchManager.QUERY)?.also { query ->
                    doMySearch(query)
                }
            }
        }
        

    Java

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.search);
            handleIntent(getIntent());
        }
    
        @Override
        protected void onNewIntent(Intent intent) {
            setIntent(intent);
            handleIntent(intent);
        }
    
        private void handleIntent(Intent intent) {
            if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
              String query = intent.getStringExtra(SearchManager.QUERY);
              doMySearch(query);
            }
        }
        

    検索の実行セクションのサンプルコードとは異なり、検索インテントを処理するためのコードがすべて、handleIntent() メソッドに含まれています。そのため、onCreate()onNewIntent() のどちらでも検索インテントを処理することができます。

    システムが onNewIntent(Intent) を呼び出すとき、アクティビティはまだ再開されていないため、getIntent() メソッドは onCreate() で受け取ったのと同じインテントを返します。これが、setIntent(Intent)onNewIntent(Intent) 内で呼び出す必要がある理由です(これにより、アクティビティによって保存されたインテントが、後で getIntent() を呼び出す場合に備えて更新されます)。

通常は、"singleTop" 起動モードを使用した 2 つ目のシナリオの方が理想的です。その理由は、検索が実行された後、ユーザーがさらに検索を実行する可能性が高いためです。また、アプリで検索可能アクティビティのインスタンスを複数作成すると、問題が発生する可能性があります。そのため、アプリ マニフェストで検索可能アクティビティの起動モードを "singleTop" に設定することをおすすめします。次に例を示します。

    <activity android:name=".SearchableActivity"
              android:launchMode="singleTop" >
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data android:name="android.app.searchable"
                          android:resource="@xml/searchable"/>
      </activity>
    

検索コンテキスト データの受け渡し

場合によっては、検索が実行されるたびに検索可能アクティビティ内で検索クエリに対して必要な改良を加えることができます。ただし、ユーザーが検索を実行しているアクティビティに基づいて検索条件を改良する場合は、システムが検索可能アクティビティに送信するインテントで追加データを提供することができます。追加データは、ACTION_SEARCH インテントに含まれる APP_DATA Bundle で渡すことができます。

このようなデータを検索可能アクティビティに渡すには、ユーザーが検索を実行可能なアクティビティの onSearchRequested() メソッドをオーバーライドし、追加データを含む Bundle を作成して、startSearch() を呼び出して検索ダイアログを有効にします。次に例を示します。

Kotlin

    override fun onSearchRequested(): Boolean {
        val appData = Bundle().apply {
            putBoolean(JARGON, true)
        }
        startSearch(null, false, appData, false)
        return true
    }
    

Java

    @Override
    public boolean onSearchRequested() {
         Bundle appData = new Bundle();
         appData.putBoolean(SearchableActivity.JARGON, true);
         startSearch(null, false, appData, false);
         return true;
     }
    

このコールバック イベントが正常に処理され、startSearch() を呼び出して検索ダイアログが有効化されると、true を返します。ユーザーがクエリを送信すると、追加したデータとともに検索可能アクティビティに渡されます。APP_DATA Bundle から余分なデータを取り出して、検索結果を絞り込むことができます。次に例を示します。

Kotlin

    val jargon: Boolean = intent.getBundleExtra(SearchManager.APP_DATA)?.getBoolean(JARGON) ?: false
    

Java

    Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
    if (appData != null) {
        boolean jargon = appData.getBoolean(SearchableActivity.JARGON);
    }
    

注意: startSearch() メソッドを onSearchRequested() コールバック メソッドの外部から呼び出さないでください。アクティビティで検索ダイアログを有効にするには、必ず onSearchRequested() を呼び出します。そうしないと、onSearchRequested() が呼び出されず、カスタマイズ(上の例の appData の追加など)が無効になります。

検索ウィジェットの使用

図 2. 「アクション ビュー」としてアクションバーに挿入した SearchView ウィジェット

SearchView ウィジェットは Android 3.0 以降で使用できます。Android 3.0 向けのアプリの開発で検索ウィジェットを使用する場合は、検索ウィジェットをアクティビティ レイアウト内に配置するのではなく、検索ウィジェットをアクション ビューとしてアプリバーに挿入することをおすすめします。図 2 に、アプリバーに挿入した検索ウィジェットの例を示します。

検索ウィジェットは検索ダイアログと同じ機能を備えています。ユーザーが検索を実行すると適切なアクティビティが開始され、検索候補を表示したり、音声検索を実行したりできます。検索ウィジェットをアクションバーに挿入できない場合は、代わりにアクティビティ レイアウト内に配置できます。

注: 検索ウィジェットをアクション ビューとして使用する場合、検索ダイアログも使用できるようにしなければならないことがあります。その場合、検索ウィジェットがアクションバー内に収まらなくなります。詳しくは、次のセクションのウィジェットとダイアログの併用をご覧ください。

検索ウィジェットの設定

検索可能構成検索可能アクティビティを作成したら、前述のとおり、Android がサポートする検索を各 SearchView で行えるようにする必要があります。そのためには、setSearchableInfo() を呼び出して、検索可能構成を表す SearchableInfo オブジェクトを渡します。

SearchableInfo への参照を取得するには、SearchManagergetSearchableInfo() を呼び出します。

たとえば、SearchViewアプリバー内でアクション ビューとして使用する場合、onCreateOptionsMenu() コールバックでウィジェットを有効にする必要があります。

Kotlin

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the options menu from XML
        val inflater = menuInflater
        inflater.inflate(R.menu.options_menu, menu)

        // Get the SearchView and set the searchable configuration
        val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
        (menu.findItem(R.id.menu_search).actionView as SearchView).apply {
            // Assumes current activity is the searchable activity
            setSearchableInfo(searchManager.getSearchableInfo(componentName))
            setIconifiedByDefault(false) // Do not iconify the widget; expand it by default
        }

        return true
    }
    

Java

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the options menu from XML
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.options_menu, menu);

        // Get the SearchView and set the searchable configuration
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
        // Assumes current activity is the searchable activity
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by default

        return true;
    }
    

必要な処理はこれだけです。これで、検索ウィジェットが設定されたので、システムによって検索クエリが検索可能アクティビティに渡されます。また、検索ウィジェットの検索候補を有効にすることもできます。

注: コールバック メソッドとイベント リスナーを使用して、ユーザー入力をすべて自分で処理することもできます。詳しくは、SearchView とそのネストされたインターフェースのリファレンス ドキュメントをご覧いただき、適切なイベント リスナーをご確認ください。

アクションバー内のアクション ビューについて詳しくは、アクション ビューとアクション プロバイダをご覧ください。

検索ウィジェットのその他の機能

SearchView ウィジェットでは以下の機能も使用できます。

送信ボタン
デフォルトでは検索クエリの送信ボタンがないため、検索を開始するにはユーザーがキーボードの Enter キーを押す必要があります。「送信」ボタンは setSubmitButtonEnabled(true) を呼び出すことによって追加できます。
検索候補のクエリの絞り込み
検索候補が有効になっている場合、デベロッパーは通常、ユーザーが候補を選択することを期待します。しかし、ユーザーは検索候補のクエリを絞り込みたいと思うかもしれません。検索ボックスに候補を挿入するボタンを各候補の横に追加して、ユーザーが候補を絞り込めるようにすることができます。そのためには、setQueryRefinementEnabled(true) を呼び出します。
検索ボックスの表示の切り替え機能
デフォルトでは、検索ウィジェットは「アイコン化」されています。つまり、検索ウィジェットはデフォルトでは検索アイコン(虫メガネ)で表示され、ユーザーがアイコンをタップすると拡大されて、検索ボックスが表示されます。デフォルトで検索ボックスを表示するには、上の例のように setIconifiedByDefault(false) を呼び出します。また、setIconified() を呼び出すことによって検索ウィジェットの表示を切り替えることもできます。

SearchView クラスには、検索ウィジェットをカスタマイズするための API が他にもいくつかあります。ただしそのほとんどは、Android システムを通じて検索クエリを送信したり、検索候補を表示したりするためのものではなく、ユーザー入力をすべて自分で処理する場合にのみ使用されます。

ウィジェットとダイアログの併用

検索ウィジェットをアクションバーにアクション ビューとして挿入し、(android:showAsAction="ifRoom" を設定して)「スペースがある場合」にアクションバー内に表示できるようにしても、検索ウィジェットがアクション ビューとして表示されず、メニュー項目がオーバーフロー メニューに表示される可能性があります。たとえば、アプリが小さい画面で実行されている場合、検索ウィジェットを他のアクション アイテムやナビゲーション要素とともに表示するための十分なスペースがアクションバーにない可能性があるため、代わりにメニュー項目がオーバーフロー メニューに表示されます。オーバーフロー メニューに表示されたメニュー項目は、通常のメニュー項目と同じように機能し、アクション ビュー(検索ウィジェット)を表示しません。

この状況に対処するには、検索ウィジェットが関連付けられているメニュー項目で、ユーザーがオーバーフロー メニューから検索ダイアログを選択したときに有効にする必要があります。そのためには、「検索」メニュー項目を処理し、onSearchRequested() を呼び出して検索ダイアログを開くように onOptionsItemSelected() を実装する必要があります。

アクションバー内の項目の動作と、この状況に対処する方法について詳しくは、アクションバーのデベロッパー ガイドをご覧ください。

音声検索の追加

android:voiceSearchMode 属性を検索可能構成に追加することで、音声検索機能を検索ダイアログまたは検索ウィジェットに追加できます。これにより、音声プロンプトを起動する音声検索ボタンが追加されます。ユーザーが音声入力を終了すると、文字起こしされた検索クエリが検索可能アクティビティに送信されます。

例:

    <?xml version="1.0" encoding="utf-8"?>
    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/search_label"
        android:hint="@string/search_hint"
        android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" >
    </searchable>
    

音声検索を有効にするには、showVoiceSearchButton を指定する必要があります。2 つ目の値 launchRecognizer では、音声検索ボタンで音声認識ツールを起動することが指定されます。文字起こしされたテキストはこのツールによって検索可能アクティビティに返されます。

音声検索の動作(使用言語、返す結果の最大数など)を指定するための属性を追加することもできます。使用可能な属性について詳しくは、検索可能構成のリファレンスをご覧ください。

注: 音声検索がアプリに適しているかどうかを慎重に検討してください。音声検索ボタンで実行された検索はすべて、検索可能アクティビティにすぐに送信されます。その際、文字起こしされたクエリをユーザーが確認することはできません。音声認識を十分にテストし、ユーザーがアプリ内で送信する可能性があるクエリのタイプを理解しておいてください。

検索候補の追加

図 3. カスタム検索候補が表示された検索ダイアログのスクリーンショット

検索ダイアログと検索ウィジェットには、Android システムのサポートにより、ユーザーが入力しているときに検索候補を表示することができます。システムは候補のリストを管理し、ユーザーが候補を選択したときのイベントを処理します。

検索候補には次の 2 種類があります。

最近のクエリに基づく検索候補
これらの候補は、ユーザーが以前にアプリ内で検索クエリとして使用した単語です。

詳しくは、最近のクエリに基づく候補の追加をご覧ください。

カスタム検索候補
これらは、ユーザーが探し求めている正しいスペルや項目をすぐに選択できるように独自のデータソースから提供する検索候補です。図 3 に、辞書アプリのカスタム検索候補の例を示します。ユーザーが候補を選択すると、すぐに定義が表示されます。

詳しくは、カスタム候補の追加をご覧ください。