2012年10月26日金曜日

メニューのレイアウトを動的に変更する

Android4.0(以降ICS)ではメニューを再描画させるためのメソッド"invalidateOptionsMenu"がFragmentManagerクラスに追加されました。

このinvalidateOptionsMenuメソッドはActivityクラスではAndroid3.0(API level11)から追加されていますが、Fragmentからメニューの再描画を促したい場合はFragmentManager#invalidateOptionsMenuを使用することが必須となっています。

このinvalidateOptionsMenuメソッドを使用することで動的にメニューのレイアウトを変更することが可能になります。

invalidateOptionsMenuメソッドの詳細は以下から。

invalidateOptionsMenuを使用したメニューのレイアウトの変更方法

invalidateOptionsMenuメソッドが呼び出されるとActivityクラスのonCreateOptionsMenuメソッドが呼ばれます。

メニューのレイアウトを変更したい場合はメニューのレイアウトのバリエーションをメニューのレイアウトファイルに定義しておいて、メニューのレイアウトを管理する変数を用意し、onCreateOptionsMenuメソッドではレイアウト管理用の変数ごとに読み込むメニューのレイアウトファイルを変更する実装がシンプルでコードの可読性も上がります。

下記のサンプルはmMenuTypeというメニューのレイアウト管理用変数を用意して、その中身の状態によって読み込むメニューのレイアウトファイルを切り替えています。

InvalidateOptionsMenuSampleActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
 * メニューレイアウト管理用変数
 */
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

1
2
3
4
5
6
7
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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のメニューを再描画しています。

0 件のコメント:

コメントを投稿