やりたいこと
MainActivityからアプリバーの検索ボタンを押すと、検索するためのアクティビティを開始し、検索用のUIが起動します。データのやり取りについては記事が長くなるので別で書こうと思います。
menuを作成
検索機能を作るための一つ目の作業として、メニューの機能から、MainActivityに表示する検索ボタンを追加する作業を行います。resフォルダにあるmenuフォルダに、メニューリソースファイルを追加しましょう。そして、menuにMenuItemを追加します。MenuItemは様々なAttributeをいじることが出来ますが、今回はicon
とshowAsAction
を設定します。iconは@android:drawable/ic_menu_search
を、showAsAction
はifRoom
を選択しましょう。
ここで、showAsActionについて軽く表にまとめてみました。細かいところですが、きちんと役割が違います。
値 | 説明 |
---|---|
ifRoom | スペースがある限り、アプリバーにアイテムをボタンとして格納。 |
withText | alwaysやifRoomなどと一緒に使う。スマホを横向きにした時、アプリバーにアイコンとタイトルを表示させる。 |
never | アプリバーではなく、オーバーフローメニュー内に表示 |
always | アプリバーに常にアイテムを配置 |
xmlファイルは以下のようになりました。 |
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.e.myapplication.MainActivity">
<item
android:id="@+id/action_search"
android:icon="@android:drawable/ic_menu_search"
android:title="action_search"
app:showAsAction="ifRoom" />
</menu>
現時点でのアプリバーの様子。検索ボタンが右端にあるのが分かります。
次に、今作った検索ボタンが押されて、検索用のActivityに遷移した先で表示するアプリバーの設定を行っていきます。これも先ほどまでと同じような方法を取ります。まず、menuフォルダから新たなメニューリソースファイルを作りましょう。前回とは異なり、Search Item
をmenuにドラッグアンドドロップしてあげてください。その後は先ほどと同じように、showAsAction
をifRoom
にするだけです。xmlは以下のようになります。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/app_bar_search"
android:icon="@drawable/ic_search_black_24dp"
android:title="activity_search"
app:actionViewClass="android.widget.SearchView"
app:showAsAction="ifRoom" />
</menu>
アプリバーは先ほどと同様の見た目をしているはずです。
検索用のActivityを作る。
新たに検索用のアクティビティを作ります。これは、MainActivityでアプリバーの検索ボタンが押された時に遷移する先のアクティビティとなります。初めに、onCreateOptionsMenu
メソッドをオーバーライドして二つ目に作ったメニューリソースファイルをインフレートしましょう。また、この次に設定する検索可能構成と検索可能アクティビティを設定した後に、SearchView
でそれらを使えるようにするための設定を行います。setOnQueryTextListener
については別の記事で説明しようと思いますが、データのやり取りに使うリスナーです。以下のようにコードを書きます。
class SearchActivity : AppCompatActivity() {
private var searchView: SearchView? = null
・
・
・
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_search, menu)
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
searchView = menu.findItem(R.id.app_bar_search).actionView as SearchView
val searchableInfo = searchManager.getSearchableInfo(componentName)
searchView?.setSearchableInfo(searchableInfo)
searchView?.isIconified
searchView?.setOnQueryTextListener(object: SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
finish()
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
return false
}
})
return true
}
検索可能性を構成する
検索クエリをアクティビティに渡したり、検索候補を表示させたりするにはxml形式で検索構成を指定する必要があります。具体的には、resフォルダ直下にxml形式のフォルダを作り、その中でsearchable
という名前のファイルを作ります。label
は必須のパラメータで、アプリやアクティビティの名前です。hint
は検索する時に「キーワードを入力」などと薄文字で表示してくれる、よくあるやつです。具体的には以下のように記述します。この他にも、検索候補や音声検索をする時にこのファイルは役立ちます。
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="単語を入力してください"
android:label="SearchActivity"/>
マニフェストファイルの設定
先ほどxml形式で指定した検索構成を適用するActivityに設定します。具体的には、以下のように該当するActivityにメタデータとインテントフィルターを挿入するだけです。下記の物をコピペするだけで大丈夫なはずです。
<activity android:name=".SearchActivity">
<intent-filter>
<action android:name="android.intent.action.SEARCH"/>
</intent-filter>
<meta-data android:name="android.app.searchable"
android:resource="@xml/searchable"/>
</activity>
MainActivity
最後にMainActivityにアプリバーの設定を追加するだけです。以下の二つのメソッドを使います。
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_search -> {
startActivity(Intent(this, SearchActivity::class.java))
true
}
else -> super.onOptionsItemSelected(item)
}
}
これで、取り敢えず記事の一番上のgifのように動作すると思います。次に、検索に使った文字列をMainActivityに送るための処理を説明しようと思いますが、それは別の記事にまとめようと思います。