Popup menusの実装方法を紹介します。
目次
ターゲットViewをクリックすることで、アンカーViewの下に表示されるメニューです。
※表示例はターゲット=アンカーViewになっています。

AndroidのMenu APIが提供するもので、Menu APIの「Popup menus」と同じ動作です。
メニューの実装
Popup menusの実装方法を静的・動的に分けて示します。
静的な実装はメニューの構成をmenuリソース(xmlファイル)で定義します。
この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の実行結果です。

ターゲット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)
}
}
}
上記の例はPopupMenu.OnMenuItemClickListenerをMainActivityで実装しています。
関連記事:
