検索インターフェースを作成する

Compose をお試しください
Jetpack Compose は、Android で推奨される UI ツールキットです。Compose で検索機能を追加する方法について説明します。

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

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

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

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

関連資料:

基本情報

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

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

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

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

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

  • 検索構成
    検索ダイアログまたは検索ウィジェットの一部の設定を行う XML ファイル。音声検索、検索候補、検索ボックスに表示するヒントのテキストなどの機能の設定がこのファイルに格納されます。
  • 検索可能アクティビティ
    検索クエリを受け取ってデータを検索し、検索結果を表示する Activity
  • 検索インターフェース(次のいずれかで提供)
    • 検索ダイアログ
      デフォルトでは、検索ダイアログは非表示になっています。ユーザーが [検索] ボタンをタップしたときに onSearchRequested() を呼び出すと、画面の一番上に表示されます。
    • SearchView ウィジェット
      検索ウィジェットを使用すると、アプリバーのアクション ビューなど、アクティビティ内の任意の場所に検索ボックスを配置できます。

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

検索可能構成を作成する

まず、検索構成と呼ばれる XML ファイルを作成する必要があります。このファイルでは、検索ダイアログまたは検索ウィジェットの特定の UI 要素を構成し、候補や音声検索などの機能の動作を定義します。このファイルには以前から searchable.xml という名前が使用されています。また、このファイルは res/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 属性は必須ではありませんが、常に指定することをおすすめします。そうすることで、ユーザーがクエリを入力する前に、検索ボックスにヒントの文字列が表示されます。ヒントは重要です。ユーザーは自分が検索できるものについて、ヒントから重要な手がかりを得ることができます。

<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 属性と、検索可能構成ファイルへの参照が設定された android:resource 属性を含める必要があります。上記の例では、res/xml/searchable.xml ファイルを指します。

検索を実行する

マニフェストで検索可能アクティビティを宣言したら、次の手順に沿って検索可能アクティビティで検索を実行します。

  1. クエリを受け取ります
  2. データを検索する
  3. 結果を提示します

クエリを受信する

ユーザーが検索ダイアログまたは検索ウィジェットから検索を実行すると、システムが検索可能アクティビティを開始して、そのアクティビティに 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 を、進行状況インジケーターの表示方法については ProgressBar をご覧ください。

結果を提示する

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

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

検索ダイアログを使用する

検索ダイアログは、左側にアプリのアイコンが付いたフローティング検索ボックスで、画面の一番上に表示されます。検索ダイアログでは、ユーザーが入力しているときに検索候補を表示できます。ユーザーが検索を実行すると、検索を実行する検索可能アクティビティに検索クエリが送信されます。

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

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

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

以下の例では、検索可能アクティビティ SearchableActivity と、検索ダイアログから実行された検索を処理するために 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>

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

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

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

検索ダイアログを呼び出す

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

たとえば、onSearchRequested() を呼び出す検索ボタンをオプション メニューまたは UI レイアウトに追加します。

また、「キーワードを入力して検索」機能を有効にすることができます。この機能は、ユーザーがキーボードで入力を開始したときに検索ダイアログを有効化します。キー入力が検索ダイアログに挿入されます。アクティビティで「キーワードを入力して検索」機能を有効にするには、アクティビティの onCreate() メソッドで setDefaultKeyMode または DEFAULT_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 つのうちのどちらかが行われます。

  • デフォルトでは、検索可能アクティビティが ACTION_SEARCH インテントを受け取って onCreate() を呼び出します。また、アクティビティの新しいインスタンスがアクティビティ スタックの一番上に追加されます。これで、検索可能アクティビティのインスタンスがアクティビティ スタック内に 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) {
        super.onNewIntent(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) {
        super.onNewIntent(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);
}

検索ウィジェットを使用する

アプリのトップバーに検索ビューが表示されている画像

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

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

検索ウィジェットを構成する

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

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) // Don't 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); // Don't iconify the widget. Expand it by default.

    return true;
}

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

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

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

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

送信ボタン
デフォルトでは検索クエリの送信ボタンがないため、検索を開始するにはユーザーがキーボードの Return キーを押す必要があります。「送信」ボタンは 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 では、音声検索ボタンで音声認識ツールを起動することが指定されます。文字起こしされたテキストはこのツールによって検索可能アクティビティに返されます。

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

検索候補を追加する

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

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

最近のクエリに基づく検索候補
これらの候補は、ユーザーが以前にアプリ内で検索クエリとして使用した単語です。詳しくは、カスタム検索候補を追加するをご覧ください。
カスタム検索候補
これらは、ユーザーが探し求めている正しいスペルや項目をすぐに選択できるように独自のデータソースから提供する検索候補です。詳しくは、カスタム検索候補を追加するをご覧ください。