Popup menusの実装

投稿日:  更新日:

Popup menusの実装方法を紹介します。

スポンサーリンク

Popup menusとは

ターゲットViewをクリックすることで、アンカーViewの下に表示されるメニューです。
※表示例はターゲット=アンカーViewになっています。

AndroidのMenu APIが提供するもので、Menu APIの「Popup menus」と同じ動作です。

スポンサーリンク

メニューの実装

Popup menusの実装方法を静的・動的に分けて示します。

静的な実装(menuリソースで定義)

静的な実装はメニューの構成をmenuリソース(xmlファイル)で定義します。

このmenuリソースはres/menuフォルダに配置する決まりです。フォルダが無ければ作成してください。

res/menuフォルダの作成

メニューの定義はmenu要素の中にitem子要素を列記するだけです。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menu_item1"
        android:title="Item 1" />
    <item
        android:id="@+id/menu_item2"
        android:title="Item 2" />
    <item
        android:id="@+id/menu_item3"
        android:title="Item 3" />
</menu>

上記のメニューの定義を、PopupMenuオブジェクトへ組み込みます。このPopupMenuオブジェクトを#show()することで、メニューが表示されます。

class MainActivity : AppCompatActivity() {
    ...
	override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
		// ViewのクリックでPopup menusを起動
        findViewById<Button>(R.id.btnSLT).setOnClickListener {
            openMenu(it, R.menu.menu_items)
        }
        findViewById<Button>(R.id.btnSRB).setOnClickListener {
            openMenu(it, R.menu.menu_items)
        }
    }
	
    fun openMenu(anchor: View, resId: Int) {
        val _popup = PopupMenu(this, anchor)
        _popup.inflate(resId)	// メニューの定義を組み込み
        _popup.show()
    }
	...
}

動的な実装(Menu#addで定義)

動的な実装はメニューを構成するアイテムをMenu#addメソッドで一つ一つ追加していく方法です。

class MainActivity : AppCompatActivity() {
    ...
	override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
		// ViewのクリックでPopup menusを起動
        findViewById<Button>(R.id.btnSLT).setOnClickListener {
            openMenu(it, R.menu.menu_items)
        }
        findViewById<Button>(R.id.btnSRB).setOnClickListener {
            openMenu(it, R.menu.menu_items)
        }
    }
	
    fun openMenu(anchor: View) {
        val _popup = PopupMenu(this, anchor)
        _popup.menu.apply {
            // groupID     itemID          order      title
            add(Menu.FIRST, Menu.FIRST + 0, Menu.NONE, "File")
            add(Menu.FIRST, Menu.FIRST + 1, Menu.NONE, "Edit")
            add(Menu.FIRST, Menu.FIRST + 2, Menu.NONE, "Help")
            // ※orderが同じ(Menu.NONEは0)時はadd順に表示
        }
        _popup.show()
    }
	...
}

サンプルの実行結果

図は上記で実装したPopup menusの実行結果です。

Popup Menusの実行結果

ターゲットViewをクリックすると、アンカーViewの下に左上を起点としたドロップダウンメニューが開いて、アイテムが現れます。ちなみに、サンプルはターゲット=アンカーViewになっています。

ドロップダウンメニューが画面の外へ出てしまうときは、メニュー全体が表示できる位置へ移動されます。

スポンサーリンク

アイテムのクリックイベント処理

PopupMenu.OnMenuItemClickListenerリスナーを実装し、PopupMenuオブジェクトへ登録します。

アイテムのクリックが行われるとPopupMenu.OnMenuItemClickListenerにコールバックが返ってきます。

引数で渡されるMenuItemが保持するitemIdを使って、どのアイテムがクリックされたかを判断します。後は判断に基づいて処理を行います(サンプルはToastを発行)。

処理を行ったらtrueを返します。

class MainActivity : AppCompatActivity(), PopupMenu.OnMenuItemClickListener {
    ...
    fun openMenu(anchor: View, resId: Int) {
        val _popup = PopupMenu(this, anchor)
        _popup.inflate(resId)
        _popup.setOnMenuItemClickListener(this)				// リスナーの登録
        _popup.show()
    }

    override fun onMenuItemClick(item: MenuItem): Boolean { // リスナーの実装
        return when (item.itemId) {
            R.id.menu_item1 -> {
                Toast.makeText(this, "Item 1", Toast.LENGTH_LONG).show()
                true
            }
            R.id.menu_item2 -> {
                Toast.makeText(this, "Item 2", Toast.LENGTH_LONG).show()
                true
            }
            R.id.menu_item3 -> {
                Toast.makeText(this, "Item 3", Toast.LENGTH_LONG).show()
                true
            }
            else -> super.onOptionsItemSelected(item)
        }
    }
}
動的な実装の場合
class MainActivity : AppCompatActivity(), PopupMenu.OnMenuItemClickListener {
    ...
    fun openMenu(anchor: View) {
        val _popup = PopupMenu(this, anchor)
        _popup.menu.apply {
            // groupID     itemID          order      title
            add(Menu.FIRST, Menu.FIRST + 0, Menu.NONE, "File")
            add(Menu.FIRST, Menu.FIRST + 1, Menu.NONE, "Edit")
            add(Menu.FIRST, Menu.FIRST + 2, Menu.NONE, "Help")
            // ※orderが同じ(Menu.NONEは0)時はadd順に表示
        }
        _popup.setOnMenuItemClickListener(this)
        _popup.show()
    }

    override fun onMenuItemClick(item: MenuItem): Boolean {
        return when (item.itemId) {
            Menu.FIRST + 0 -> {
                Toast.makeText(this, "File", Toast.LENGTH_LONG).show()
                true
            }
            Menu.FIRST + 1 -> {
                Toast.makeText(this, "Edit", Toast.LENGTH_LONG).show()
                true
            }
            Menu.FIRST + 2 -> {
                Toast.makeText(this, "Help", Toast.LENGTH_LONG).show()
                true
            }
            else -> super.onOptionsItemSelected(item)
        }
    }
}

上記の例はPopupMenu.OnMenuItemClickListenerをMainActivityで実装しています。

スポンサーリンク

関連記事:

Material Design ComponentsにMenusというカテゴリがあります。 「Menus(メニュー)」なので、言葉のとおり、選択する項目を一覧表示する機能です。 Menusはメニューの表現方法によって、幾つかの種類があります。 このMenusの種類と特徴を紹介します。 ...
スポンサーリンク