woshidan's blog

あいとゆうきとITと、とっておきの話。

ToolbarのMenuItemを一度表示した後に切り替えたい

ToolbarのMenuItemを、その後のActivityの状況が変化するなりして切り替えたい*1といったことが稀に良くあります。

そう言う場合、ActivityにToolbarを置いている場合は下記のようなコードでとりあえず対応可能です。

// Activity内
    private int mMenuResourceId = R.menu.menu_main;

    // Menuを切り替えたい箇所から呼び出す
    public void changeMenuItem(int menuResourceId) {
           this.mMenuResourceId = menuResourceId;
           supportInvalidateOptionsMenu();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(mMenuResourceId, menu);
        return true;
    }

しかし、すっかり忘れていたのですが、Menuリソースには<group>という要素があり、<group>ごとに<menu>要素、<item>要素の表示、非表示を設定することが出来ます。

なので、Menuリソースの設定自体は1度にして、Menu#setGroupVisibleメソッドを用いて、groupごとに<menu>要素の表示、非表示を設定した方がスマートなのかもしれません。

メニュー | Android Developers

下記がMenu#setGroupVisibleメソッドを用いた場合のサンプルコードです。

package com.example.woshidan.fragmentmenutest;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

public class MainFragment extends Fragment {
    static final String LOGTAG = "MainFragment";
    private FloatingActionButton fab;
    private int menuKind = 0;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle bundle) {
        setHasOptionsMenu(true);
        View view =  inflater.inflate(R.layout.content_main, viewGroup, false);
        final Toolbar toolbar = (Toolbar)view.findViewById(R.id.toolbar);
        toolbar.inflateMenu(R.menu.menu_main);
        setMenuItemVisibility(toolbar.getMenu(), menuKind);

        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.action_play:
                        Log.v(LOGTAG,"menu action_play is pushed");
                        break;
                    case  R.id.action_send:
                        Log.v(LOGTAG,"menu action_send is pushed");
                        break;
                    case R.id.action_settings:
                        Log.v(LOGTAG,"menu action_settings is pushed");
                        break;
                    default:
                        Log.v(LOGTAG,"menu others is pushed");
                        break;
                }
                return false;
            }
        });

        fab = (FloatingActionButton) view.findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setMenuItemVisibility(toolbar.getMenu(), menuKind);
                menuKind = (menuKind + 1) % 3;
            }
        });
        return view;
    }

    private void setMenuItemVisibility(Menu menu, int visiblePosition) {
        menu.setGroupVisible(R.id.menu_main_3, false);
        menu.setGroupVisible(R.id.menu_main_1, false);
        menu.setGroupVisible(R.id.menu_main_2, false);
        switch (visiblePosition) {
            case 0:
                menu.setGroupVisible(R.id.menu_main_1, true);
                break;
            case 1:
                menu.setGroupVisible(R.id.menu_main_2, true);
                break;
            case 2:
                menu.setGroupVisible(R.id.menu_main_3, true);
                break;
            default:
                menu.setGroupVisible(R.id.menu_main_1, true);
                break;
        }
    }
}

f:id:woshidan:20160315235827g:plain

*1:たとえば、ViewPagerでスワイプしてて表示されるものの中身によってはメニューを変えたい