ワシはワシが育てる

週刊少年ジャンプと任天堂のゲームが三度のメシより好きです。

初めてDrawerLayoutを使った時のメモ(メニューの動的切り替えなど)

巷でハンバーガーアイコンと呼ばれるDrawerLayoutを初めて使った際に生じた問題の解決法についてまとめてみました。

Fragmentによるページの挿入

FragmentTransactionを利用します。
例えばidがhogeのViewに対してFugaFragmentのFragmentを挿入する場合は以下のように記述します。

// android.support.v4を利用しています
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
FugaFragment fuga = new FugaFragment();

ft.replace(R.id.hoge, fuga, "fuga");
ft.addToBackStack(null);
ft.commit();

必ずしもトランザクションを利用する必要はありませんが、バックボタンで戻ったり続く要件を満たす場合などに何かと利用シーンがあるので、トランザクションはセオリーなようです。

既に見えているメニューが呼び出された場合

DrawerLayoutにホームというメニューがあり、既にホームが表示されているにも関わらずホームのメニューが押された場合、トランザクションの処理を回避する必要があります。

そのような場合は、Fragmentが表示されているかで分岐すると良いでしょう。
また一度生成したFragmentは再利用することができるので、そのチェックも行っておきます。

HomeFragment homeFragment = (HomeFragment)getSupportFragmentManager().findFragmentByTag("home");
if (homeFragment == null) {
  homeFragment = new HomeFragment();
}

if (!homeFragment.isVisible()) {
  ft.replace(R.id.hoge, homeFragment, "home");
  ft.addToBackStack(null);
  ft.commit();
}

Fragmentごとにアクションバーのメニューを切り替える

メニューを動的に切り替える場合は、onPrepareOptionsMenuをオーバーライドします。

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
  menu.clear();

  if (homeFragment.isVisible()){
     getMenuInflater().inflate(R.menu.hoge, menu);
  }

  return super.onPrepareOptionsMenu(menu);
}

DrawerLayoutのメニューがクリックされた時に、アクティブなメニューのインデックスを取っておき、インデックスの数値によって切り替えるなどしたほうがスマートに感じるかもしれませんが、バックボタンの対応が必要なため、僕の場合は対象のFragmentが見えているかによって対応しました。
(ただ他のソースを参照したわけではないので、おかしなやり方かもしれません)

↑普通にFragment内でonCreateOptionsMenuをオーバーライドするだけで大丈夫でした。

onPrepareOptionsMenuはinvalidateOptionsMenu()によって呼び出されるので、DrawerToggleが開閉した際など必要に応じて記述します。
また肝心のバックボタン対策をしましょう。

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
  @Override
  public void onBackStackChanged() {
    invalidateOptionsMenu();
  }
});

これでバックボタンが押された場合にもメニューの切り替えに対応できます。