Androidアプリ開発

PopupMenuの表示位置と
メニューの間隔を調整する

この記事は約18分で読めます。
記事内に広告が含まれています。
スポンサーリンク

この記事は Androidスマホ用のアプリ開発の中で、
今後の開発で再使用性が高いと思われるコーディングをまとめたものです。
Java での開発経験、XML構文規則、Android のアプリ開発経験がある方を対象としています。
Android のアプリ開発でお役にたててれば、嬉しいです。
(これから Android のアプリ開発や Java での開発を始めたい方への案内は、
記事の最後で紹介します)

この記事のテーマ


PopupMenuの表示位置とメニューの間隔を調整する

RecyclerViewのアイテムにポップアップメニューを表示するサンプル動画です。
ポップアップメニューの表示位置とメニューアイテムの間隔を変更するコーディングを解説します。

DIREZZA β11はジムカーナ競技での上位入賞を目標にしたハイグリップスポーツタイヤです♪

ポイント

Androidアプリでメニュー表示する場合、ActionMenuViewPopupMenuを使用します。
ActionMenuViewはメニューを開くためのオブジェクト定義が必要に対して、PopupMenuは不要です。
PopupMenuは画面レイアウト上の任意のオブジェクトのリスナーを使ってメニューを開きます。
PopupMenuの場合、メニューを表示する位置がリスナーを設定したオブジェクトの下側です。
また、メニューのアイテムの間隔が広く、メニュー操作の対象がわかりにくい。
今回は、PopupMenuの表示位置とメニューの間隔を調整する実装方法を紹介します。

メニューを追加する

RecyclerViewのアイテムにポップアップメニューを実装はこちら↓↓↓

実装方法

メニューを表示する位置の調整はメニューを表示する位置がリスナーを設定したオブジェクトの位置に表示する特性を利用します。
実際のイベント処理を記述するオブジェクトとメニューを表示するオブジェクトを使います。
メニューのアイテム間隔の調整はContextThemeWrapperを使用して、PopupMenuのスタイルを定義します。

ContextThemeWrapper

メニュー表示の位置を調整する

RecyclerViewのアイテム上のImageView(img_item)をタップするとメニューを表示します。
メニューを表示する位置はImageView(img_item)の中心より左上とします。
メニューを表示する位置をImageView(dummy)、ImageView(img_item)でタップイベントを受けます。

◎RecyclerViewのアイテム定義

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="@android:color/transparent">
    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="142dp"
        android:layout_marginTop="4dp"
        android:layout_marginStart="1dp"
        android:layout_marginEnd="1dp"
        android:orientation="vertical"
        tools:ignore="UselessParent">
        <androidx.cardview.widget.CardView
            android:id="@+id/card"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:alpha="0.25"
            app:cardCornerRadius="8dp"
            app:cardElevation="0dp">
        <ImageView
            android:id="@+id/img_item"
            android:scaleType="centerCrop"
            android:layout_width="120dp"
            android:layout_height="120dp"
            tools:ignore="ContentDescription" />
        </androidx.cardview.widget.CardView>
        <ImageView
            android:id="@+id/dummy"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_margin="24dp"
            tools:ignore="ContentDescription" />
        <TextView
            android:id="@+id/text_item"
            android:gravity="bottom|center"
            android:layout_marginTop="70dp"
            android:layout_width="122dp"
            android:layout_height="70dp"
            android:textSize="14sp"
            android:textStyle="bold"/>
    </FrameLayout>
</LinearLayout>

◎メニュー定義

<?xml version="1.0" encoding="utf-8"?>
<menu
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu62" android:title="@string/menu6"/>
    <item android:id="@+id/menu92" android:title="@string/menu9"/>
    <item android:id="@+id/menu22" android:title="@string/menu2"/>
    <item android:id="@+id/menu32" android:title="@string/menu3"/>
    <item android:id="@+id/menu42" android:title="@string/menu4"/>
</menu>

メニュー項目は、strings.xmlに記述します。

◎RecyclerViewのアイテム表示とメニュー表示

  :
        partsAdapter = new HorizontalListView.ArrayAdapter(partsList) {
            @Override
            public View getView(ViewGroup parent) {
                return LayoutInflater.from(parent.getContext()).inflate(R.layout.item_horizontal, parent,false);
            }
            @Override
            public void onBindView(View view, Object data, int position) {
                // パーツ名
                TextView textView1 = view.findViewById(R.id.text_item);
                textView1.setText(HtmlCompat.fromHtml(String.format("<big><b><u>%s</u></b></big>",partsList.get(position).item), FROM_HTML_MODE_COMPACT));
                // イメージ表示
                CardView card = view.findViewById(R.id.card);
                ImageView imageView = view.findViewById(R.id.img_item);
                imageView.setImageResource(R.drawable.no_image);
                imageView.setScaleType(CENTER_INSIDE);
                // メニュー表示用ダミー
                ImageView dummy = view.findViewById(R.id.dummy);
                imageView.setOnClickListener(view2 -> dummy.performClick());
                dummy.setOnClickListener(view1 -> {
                        ContextThemeWrapper contextThemeWrapper = new ContextThemeWrapper(view1.getContext(), R.style.PopupMenu);
                        PopupMenu popup = new PopupMenu(contextThemeWrapper, view1);
                        popup.setOnMenuItemClickListener(item -> {
                            partsListPosition = position;
                            itemId = item.getItemId();
                            Intent intent;
                            switch (itemId) {
                                case R.id.menu62:    // パーツを修正する
                    :
                                    break;
                                case R.id.menu92:    // パーツを削除する
                    :
                                    break;
                                case R.id.menu22:    // イメージを表示する
                    :
                                    break;
                                case R.id.menu32:    // イメージを選択する
                    :
                                    break;
                                case R.id.menu42:    // カメラで撮影する
                    :
                                    break;
                                default:
                            }
                            return false;
                        });
                        popup.inflate(R.menu.menu_parts);
                        popup.show();
                    }
                });
            }
        };
        partsView.setAdapter(partsAdapter);
  :

ImageView(img_item)のタップイベントをImageView(dummy)にハンドリング(performClick)します。

メニューのアイテム間隔の調整する

メニューのアイテム間隔はスタイルリソースファイル(style.xml)にスタイルを定義します。
アイテム間隔はlistPreferredItemHeightSmallで指定します。
スタイルの適用はContextThemeWrapperを使用してスタイルを適用したContextを作成、PopupMenuをインスタンス化します。

スタイルリソースファイル

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="PopupMenu" parent="@android:style/Widget.PopupMenu">
        <item name="android:colorBackground">@color/white</item>
        <item name="android:textColor">@color/black</item>
        <item name="android:listPreferredItemHeightSmall">36dp</item>
    </style>
  :
</resources>

◎スタイルの適用

  :
    dummy.setOnClickListener(view1 -> {
        ContextThemeWrapper contextThemeWrapper = new ContextThemeWrapper(view1.getContext(), R.style.PopupMenu);
        PopupMenu popup = new PopupMenu(contextThemeWrapper, view1);
        :
        popup.inflate(R.menu.menu_parts);
        popup.show();
    });
  :

今回は、ここまでです。

PopupMenuの表示位置とメニューの間隔を調整しているAndroidアプリです。

誤字脱字、意味不明でわかりづらい、
もっと詳しく知りたいなどのご意見は、
このページの最後にある
コメントか、
こちらから、お願いいたします♪

ポチッとして頂けると、
次のコンテンツを作成する励みになります♪

ブログランキング・にほんブログ村へ

これからAndroidのアプリ開発やJavaでの開発を始めたい方へ

アプリケーション開発経験がない方や、アプリケーション開発経験がある方でも、Java や C# などのオブジェクト指向言語が初めての方は、Android のアプリ開発ができるようになるには、かなりの時間がかかります。
オンラインスクールでの習得を、強くおススメします。

未経験者からシステムエンジニアを目指すのに最適です。まずは無料相談から♪

未経験者からプログラマーを目指すのに最適です。まずは無料カウンセリングから♪

カリキュラムとサポートがしっかりしています。お得なキャンペーンとかいろいろやっています♪

ゲーム系に強いスクール、UnityやUnrealEngineを習得するのに最適です。まずは無料オンライン相談から♪

参考になったら、💛をポッチとしてね♪

スポンサーリンク
msakiをフォローする
スポンサーリンク

コメント欄

タイトルとURLをコピーしました