ActionBarにメニューの「・・・」を常時表示してサブメニューにアイコンを表示する

  • 50
    いいね
  • 2
    コメント
この記事は最終更新日から1年以上が経過しています。

背景

qiita1.png

ActionBarSherlock や Support Library の ActionBarActivity を使えば Android 2.x でも ActionBar 付きの Activity を作れるわけですが、物理メニューキーがある端末ではActionBarに「・・・」(いわゆるthree dots)が表示されません。

Androidのデザインガイドライン的にはこれが正しい振る舞いと思いますし個人的にはそれでかまわないんですが、サポートの手間がものすごくかかる(「もし画面右上に「・・・」ボタンがあればそれを押し、なければ端末のメニューボタンを押して」を毎回説明する)ので常時表示することができればウレシイなと思って調べてみました。

ついでに上記スクリーンショットのように、サブメニューにアイコンを付けられるようになったのでメニュー項目が若干分かりやすくなるというメリットもあります。

余談ですが、「端末のメニューボタンを押してください」とユーザーに伝えたら「メニューボタンって何ですか?」って質問される場合もありました。以下はそんな世界にだけ通用するフィクションみたいなものだと思って頂ければ。。

実現方法

showAsAction="always" のic_action_overflowのボタンを表示して、そのサブメニューとしてメニュー項目を作成します。

res/menu/main_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:yourapp="http://schemas.android.com/apk/res-auto" >

    <!-- トップページ -->
    <item
        android:id="@+id/menu_toppage"
        android:icon="@drawable/icon32_ic_menu_home"
        android:title="トップページ"
        yourapp:showAsAction="always"/>

    <!-- 共有 -->
    <item
        android:id="@+id/menu_share"
        android:icon="@drawable/icon32_dummy_space"
        android:title="共有"
        yourapp:showAsAction="always"/>

    <!-- Options -->
    <item
        android:id="@+id/overflow_options"
        android:icon="@drawable/ic_action_overflow_dark"
        android:title="Menu"
        yourapp:showAsAction="always">
        <menu>

            <!-- ブラウザで開く -->
            <item
                android:id="@+id/menu_share_by_browser"
                android:icon="@drawable/icon32_dummy_space"
                android:title="ブラウザで開く"
                yourapp:showAsAction="never"/>

            <!-- URLの確認 -->
            <item
                android:id="@+id/menu_show_url"
                android:icon="@drawable/icon32_dummy_space"
                android:title="URLの確認"
                yourapp:showAsAction="never"/>

            <!-- ページ内検索 -->
            <item
                android:id="@+id/menu_text_find_start"
                android:icon="@drawable/icon32_dummy_space"
                android:title="ページ内検索"
                yourapp:showAsAction="never"/>
...
        </menu>
    </item>

</menu>

※日本人向けのアプリなのでandroid:title属性に直接書いちゃってるけど当然文字列リソースを用意すべきですよ。

※android:icon属性を@drawable/icon32_dummy_spaceにしているのは実行時に onPrepareOptionsMenu で IconicDroidのアイコンに差し替えるためです。

MainActivity.java
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        final MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);

        mainMenu = menu;

        return super.onCreateOptionsMenu(menu);
    }

詳細は stackoverflowのこの回答 を参照してください。ic_action_overflow などのリソースもリンク先にあります。

メニューボタン押下時のサブメニュー表示

上記だけだと物理メニューキーを押してもサブメニューは出てくれないのでそこも自力でハンドリングしてあげます。

    private Menu mainMenu;
...
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        final MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);

        mainMenu = menu;

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
...
        final int action = event.getAction();
        final int keyCode = event.getKeyCode();
        if (action == KeyEvent.ACTION_UP) {
            // メニュー表示
            if (keyCode == KeyEvent.KEYCODE_MENU) {
                if (mainMenu != null) {
                    mainMenu.performIdentifierAction(R.id.overflow_options, 0);
                }
                return true;
            }
        }
...
    }

参考