メニューのレイアウトを動的に変更する
Android4.0(以降ICS)ではメニューを再描画させるためのメソッド“invalidateOptionsMenu”がFragmentManagerクラスに追加されました。
このinvalidateOptionsMenuメソッドはActivityクラスではAndroid3.0(API level11)から追加されていますが、Fragmentからメニューの再描画を促したい場合はFragmentManager#invalidateOptionsMenuを使用することが必須となっています。
このinvalidateOptionsMenuメソッドを使用することで動的にメニューのレイアウトを変更することが可能になります。
invalidateOptionsMenuメソッドの詳細は以下から。
invalidateOptionsMenuを使用したメニューのレイアウトの変更方法
invalidateOptionsMenuメソッドが呼び出されるとActivityクラスのonCreateOptionsMenuメソッドが呼ばれます。
メニューのレイアウトを変更したい場合はメニューのレイアウトのバリエーションをメニューのレイアウトファイルに定義しておいて、メニューのレイアウトを管理する変数を用意し、onCreateOptionsMenuメソッドではレイアウト管理用の変数ごとに読み込むメニューのレイアウトファイルを変更する実装がシンプルでコードの可読性も上がります。
下記のサンプルはmMenuTypeというメニューのレイアウト管理用変数を用意して、その中身の状態によって読み込むメニューのレイアウトファイルを切り替えています。
InvalidateOptionsMenuSampleActivity.java
/** * メニューレイアウト管理用変数 */ public static int mMenuType = 1; /** * メニューのレイアウトファイルmenu_aを表す */ public static final int MENU_TYPE_A = 1; /** * メニューのレイアウトファイルmenu_bを表す */ public static final int MENU_TYPE_B = 2; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button btn = (Button) findViewById(R.id.change_menu_button); btn.setOnClickListener(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { // メニューレイアウト管理用変数が切り替わる度にメニューのレイアウトを切り替える switch (mMenuType) { case MENU_TYPE_A: getMenuInflater().inflate(R.menu.menu_a, menu); break; case MENU_TYPE_B: getMenuInflater().inflate(R.menu.menu_b, menu); break; default: break; } return super.onCreateOptionsMenu(menu); }
メニューのレイアウトを切り替える仕組みができたところで、実際にFragmentからメニューを更新してみましょう。
まず、InvalidateOptionsMenuSampleActivity.javaにFragmentをコミットするための処理を追加します。
下記のコードでは画面内のボタンが押下される度にFragmentがコミットされます。
InvalidateOptionsMenuSampleActivity.java
public void onClick(View v) { // フラグメントをコミットする InvalidateOptionsMenuFragment fragment = new InvalidateOptionsMenuFragment(); FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.add(R.id.sample_fragment, fragment); ft.commit(); }
次にInvalidateOptionsMenuFragmentのコードを下記に記述します。
このFragmentはonResumeが呼ばれる度に親Activityのメニューレイアウト管理用変数を変更し、メニューの再描画を行います。
InvalidateOptionsMenuFragment.java
public class InvalidateOptionsMenuFragment extends Fragment{ public InvalidateOptionsMenuFragment() { } @Override public void onResume() { super.onResume(); // 親Activityのメニュー管理用変数を切り替える switch (InvalidateOptionsMenuSampleActivity.mMenuType) { case InvalidateOptionsMenuSampleActivity.MENU_TYPE_A: InvalidateOptionsMenuSampleActivity.mMenuType = InvalidateOptionsMenuSampleActivity.MENU_TYPE_B; break; case InvalidateOptionsMenuSampleActivity.MENU_TYPE_B: InvalidateOptionsMenuSampleActivity.mMenuType = InvalidateOptionsMenuSampleActivity.MENU_TYPE_A; break; default: break; } getFragmentManager().invalidateOptionsMenu(); } }
21行目でFragmentManager#invalidateOptionsMenuメソッドを使用して、親Activityのメニューを再描画しています。