【Menu】Fragmentにメニューを表示させる方法

やりたいこと

Fragment上にメニューを配置、および押されたときの動作を実装したい。

手順

menuを作成する

表示したいmenuをXMLファイルで作成しましょう。
各メニューはitemタグで表します。

ここでは例として、削除アイコン編集アイコン送信アイコンを表示してみましょう。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_delete" android:icon="@drawable/ic_delete" android:title="削除" app:showAsAction="always" /> <item android:id="@+id/menu_edit" android:icon="@drawable/ic_edit" android:title="編集" app:showAsAction="always" /> <item android:id="@+id/menu_send" android:icon="@drawable/ic_send" android:title="送信" app:showAsAction="always" />
</menu>
MEMO

メニューのXMLファイルはres>menuに作成します。
menuディレクトリがなければ、resを右クリックし、New>Android Resource Directoryでディレクトリを作成しよう。

setHasOptionsMenu(true)を呼ぶ

Activityと異なり、FragmentでMenuを表示する場合にはsetHasOptionsMenuメソッドを呼ぶ必要があります。
引数にtrueを渡すと表示されるようになりますよ。

例として、onCreateの中で実行しています。

override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true)
}
注意

忘れがちなので気をつけて。setHasOptionsMenu(true)が実行されないとonCreateOptionsMenu(後述)が呼ばれません。

onCreateOptionsMenuをオーバーライドする

メニューを表示したいFragmentでonCreateOptionsMenuをオーバーライドします。
inflateメソッドの第1引数に、先ほど作成したmenuを渡してあげましょう。

override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { inflater?.inflate(R.menu.menu_main_fragment, menu)
}
MEMO

Activityと異なり、Boolean値をreturnする必要はありません。

onOptionsItemSelectedをオーバーライドする

最後にメニューをタップされたときの動作を実装するため、メニューを表示したいFragmentでonOptionsItemSelectedをオーバーライドします。
押されたMenuItemが引数で渡ってくるので、itemIdでどのメニューが押されたか判定しましょう。

ここでは例として、各メニューが押されたらToastを表示するようにしています。

override fun onOptionsItemSelected(item: MenuItem?): Boolean { when (item?.itemId) { R.id.menu_delete -> { Toast.makeText(requireContext(), "削除ボタンが押されました", Toast.LENGTH_SHORT).show() return false } R.id.menu_edit -> { Toast.makeText(requireContext(), "編集ボタンが押されました", Toast.LENGTH_SHORT).show() return false } R.id.menu_send -> { Toast.makeText(requireContext(), "送信ボタンが押されました", Toast.LENGTH_SHORT).show() return false } } return true
}

まとめ

Fragmentでメニューを表示するには

  • menuを作成する
  • setHasOptionsMenu(true)を呼ぶ
  • onCreateOptionsMenuをオーバーライドして、メニューをセット
  • onOptionsItemSelectedをオーバーライドして、メニュー押下時の処理を記述

を行いましょう。

実装は以上です。

ソースコード

MainFragment.kt

package katapiproject.practice
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.*
import android.widget.Toast
class MainFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_main, container, false) } override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { inflater?.inflate(R.menu.menu_main_fragment, menu) } override fun onOptionsItemSelected(item: MenuItem?): Boolean { when (item?.itemId) { R.id.menu_delete -> { Toast.makeText(requireContext(), "削除ボタンが押されました", Toast.LENGTH_SHORT).show() return false } R.id.menu_edit -> { Toast.makeText(requireContext(), "編集ボタンが押されました", Toast.LENGTH_SHORT).show() return false } R.id.menu_send -> { Toast.makeText(requireContext(), "送信ボタンが押されました", Toast.LENGTH_SHORT).show() return false } } return true } companion object { fun newInstance() = MainFragment() }
}

menu_main_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_delete" android:icon="@drawable/ic_delete" android:title="削除" app:showAsAction="always" /> <item android:id="@+id/menu_edit" android:icon="@drawable/ic_edit" android:title="編集" app:showAsAction="always" /> <item android:id="@+id/menu_send" android:icon="@drawable/ic_send" android:title="送信" app:showAsAction="always" />
</menu>