Androidアプリ内でこういう処理を実現したい
- なんの変哲もないボタンがある
- 押した時にポップアップを表示したい
- リストとかドロップダウン表示したい
こういう処理はPopupMenuを使えばできます。
しかも予想以上に簡単に実装できたので、
ポップアップ表示方法をまとめたいと思います。
主にKotlinでのコード例です。(Javaでも同様)
このページの目次
初めにPopupMenuの概要に少し触れておく
これはAPIレベル11以降で使える標準APIです。
▼ 公式リファレンスでのPopupMenuの概要
A PopupMenu displays a Menu in a modal popup window anchored to a View. The popup will appear below the anchor view if there is room, or above it if there is not. If the IME is visible the popup will not overlap it until it is touched. Touching outside of the popup will dismiss it.
引用元 : https://developer.android.com/reference/android/widget/PopupMenu.html
▼ 上記リファレンスの意訳
PopupMenuは特定のViewに紐づけられて表示されるモーダルポップアップです。ポップアップは紐づけされたViewの下に余白があれば下部に、そうでないなら上部に表示されます。もしIMEが表示されてるなら、タッチされるまで重なり合いません。それからポップアップ外側をタッチすると消せます。
この説明にあるように、PopupMenuはアンカービュー(例 : ボタン)に対してポップアップ表示できる便利なものです。表示場所も適切に判断してくれます。
特別なライブラリも必要ないのが良い
まずボタンとかのレイアウトを定義しよう
ここはポップアップとは直接関係ありません。
ボタンが1つだけのレイアウトを作ってみます。
▼ このようなレイアウトにした(XML)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/show_popup_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> |
本当にシンプルな配置です。
ボタンIDは show_popup_button にしました。
それからPopupMenuはレイアウト上に配置する必要はありません。上記レイアウトのようにポップアップ表示用のボタンを配置しただけです。
レイアウトについては他に言うことなし
ボタン押下時にPopupMenu表示するコード例
それではPopupMenuでポップアップ表示します。
次のようなコードで簡単に表示できました。
▼ 例えばこのようなコード(Kotlin)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/// ポップアップ表示ボタン val button = findViewById<Button>(R.id.show_popup_button) /// ポップアップメニュー val popup = PopupMenu(this, button) popUp.menu.add(Menu.NONE, 0, 0, "Cupcake") popUp.menu.add(Menu.NONE, 1, 1, "Donut") popUp.menu.add(Menu.NONE, 2, 2, "Eclair") popUp.menu.add(Menu.NONE, 3, 3, "Froyo") popUp.menu.add(Menu.NONE, 4, 4, "Gingerbread") popUp.setOnMenuItemClickListener { menuItem -> val id = menuItem.itemId button.text = menuItem.title if (id==0){ /// @TODO } else if(id==1){ /// @TODO } else if (id==2){ /// @TODO } else if (id==3){ /// @TODO } else if (id==4){ /// @TODO } false } button.setOnClickListener { /// 押下時にポップアップ表示 popUp.show() } |
このコードの冒頭で PopupMenu(this, button) とあるように第2引数にアンカービューを指定です。この場合だとボタン押下時にその下(あるいは上)に表示されます。
あとPopupMenu.menu.addメソッドについて
▼ 各引数はそれぞれ次の意味を持つ
- 第1引数 : groupId
ポップアップアイテムのグループID。アイテムをまとめたり一括して常態変更させるアイテムグループを定義できる。ここでは不要なので Menu.NONE を指定
- 第2引数 : itemId
ポップアップアイテムそのもののID。このIDは menuItem.itemId などのように選択時に取得できる。必要ないなら Menu.NONE を指定してもOK
- 第3引数 : order
オーダーすなわち順序。かならずしも追加順に並べたいとは限らないため、順序を指定したいならこのパラメーターを使えばいい
- 第4引数 : titile or titleRes
アイテムタイトルの文字列あるいは文字列リソースID。この値は menuItem.title から選択時に取得できる。分かりやすいタイトルを付ければいい
こういう感じになってます。
あとはリスナーで選択時の処理をするだけです。
実際のPopupMenuの見た目とか動かしてみた様子
早速PopupMenuを表示してみました。
▼ ポップアップ表示の見た目
▼ 実際に動かしてみた動作例GIF(note)
期待通りに動いてくれました。
実装が本当にシンプルで分かりやすいです。