【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>