web-dev-qa-db-ja.com

Android-invalidateOptionsMenu()の正しい使用法

私はinvalidateOptionsMenu()で多くのことを検索してきましたが、それが何をするのか知っています。しかし、この方法が役立つ実際の例を考えることはできません。

たとえば、新しいMenuItemActionBarに追加したい場合、onCreateOptionsMenu(Menu menu)からメニューを取得し、任意のボタンのアクションで使用できます。

さて、私の本当の質問に、invalidateOptionsMenu()を使用するonlyの方法に従っていますか?

bool _OtherMenu;
protected override void OnCreate (Bundle bundle)
{
    _OtherMenu = false;
    base.OnCreate (bundle);
    SetContentView (Resource.Layout.Main);
    Button button = FindViewById<Button> (Resource.Id.myButton);
    button.Click += delegate
    {
        if(_OtherMenu)
            _OtherMenu = false;
        else
            _OtherMenu = true;

        InvalidateOptionsMenu ();
    };
}

public override bool OnCreateOptionsMenu (IMenu menu)
{
    var inflater = this.SupportMenuInflater;
    if(_OtherMenu)
        inflater.Inflate (Resource.Menu.another_menu, menu);
    else
        inflater.Inflate (Resource.Menu.main_activity_menu, menu);

    return base.OnCreateOptionsMenu (menu);
}

ボタンをクリックすると、別のメニューが表示されます。もう一度ボタンをクリックすると、前のメニューが表示されます。

追伸C#構文でごめんなさい。

33
Bugs Happen

invalidateOptionsMenu()はAndroidを表すために使用され、メニューの内容が変更されたため、メニューを再描画する必要があります。たとえば、実行時に別のメニュー項目を追加するボタンをクリックするか、メニュー項目グループを非表示にします。この場合、システムがUIで再描画できるように、invalidateOptionsMenu()を呼び出す必要があります。このメソッドは、必要なメニュー操作を実装するonPrepareOptionsMenu()を呼び出すOSのシグナルです。さらに、OnCreateOptionsMenu()はアクティビティ(フラグメント)の作成中に1回だけ呼び出されるため、このメソッドではランタイムメニューの変更を処理できません。

すべては documentation にあります:

システムはonCreateOptionsMenu()を呼び出した後、ユーザーが入力したメニューのインスタンスを保持し、何らかの理由でメニューが無効化されない限り、onCreateOptionsMenu()を再度呼び出しません。ただし、onCreateOptionsMenu()は、初期メニュー状態を作成するためにのみ使用し、アクティビティのライフサイクル中に変更を加えることはできません。

アクティビティのライフサイクル中に発生するイベントに基づいてオプションメニューを変更する場合は、onPrepareOptionsMenu()メソッドで変更できます。このメソッドは、現在存在するMenuオブジェクトを渡すので、アイテムの追加、削除、無効化など、変更できます。 (フラグメントはonPrepareOptionsMenu()コールバックも提供します。)

On Android 2.3.x以前では、システムは、ユーザーがオプションメニューを開く(メニューボタンを押す)たびにonPrepareOptionsMenu()を呼び出します。

On Android 3.0以降では、オプションバーはメニュー項目がアクションバーに表示されるときに常に開いていると見なされます。イベントが発生してメニューの更新を実行する場合は、 invalidateOptionsMenu()を使用して、システムがonPrepareOptionsMenu()を呼び出すように要求します。

65
Alexander Zhak

これを使用して、アプリのライフサイクル中に新しいメニューを再読み込みします。

新しい:

getActivity().invalidateOptionsMenu();

古い

ActivityCompat.invalidateOptionsMenu(getActivity());
18
itzhar

メソッドonPrepareOptionsMenu()をオーバーライドし、同じメソッドでアクションメニューの更新コードを記述し、フラグメントを使用している場合は、setHasOptionsMenu(true);onCreateView()を追加する必要があります。

それがあなたを助けることを願っています

2
Richa

私が見つけた1つの使用法は、onResumeonCreateOptionsMenu/onPrepareOptionsMenuの間の操作の順序を強制することです。 (少なくともプラットフォーム22の時点で)自然な順序は、特にデバイスの向きを変えるときに、フロップで反転するようです。

invalidateOptionsMenu()のonResume()を呼び出すと、onPrepareOptionsMenuがonResumeの後に呼び出されることを保証します(前にさらに呼び出すこともできます)。たとえば、これにより、onResumeで取得したデータに基づいてメニュー項目を有効にすることができます。

2
Goose

私のために働いた最良の方法を以下に示します

  1. OnCreateOptionsMenu(...)にメニューの初期状態を入れます

  2. InvalidateOptionsMenu()を使用して、onCreateOptionsMenu(...)およびonPrepareOptionsMenu(...)を強制します。

  3. OnPrepareOptionsMenu(...)でmenu.clear()を呼び出して、メニューからすべてのアイテムを削除します。

  4. まだonPrepareOptionsMenu(...)で、クリア後に動的なメニュー変更を配置します

お役に立てれば...

1

古いですが、これが将来の誰かの助けになることを願っています。

実際のシナリオで私が見つけた1つの使用法:

データベースに保存されているアイテムのリストがあり、2つのアクティビティがあるとします。

  1. DisplayActivity:データベースから取得した後にこれらのオブジェクトを表示します。
  2. EditActivity:既存のアイテムを編集し、データベースに保存するために使用されます。

DisplayActivityからEditActivityに移動するためのオプションをいくつか用意することにしました。

  • 最初:真新しいアイテムをデータベースに追加します。
  • Second:既存のアイテムを編集します。

コードを複製して繰り返さないように、両方の目的でEditActivityを使用することにしました。

そのため、各目的に応じてオプションメニューをカスタマイズします。この場合、onCreateOptionsMenu()を使用してデフォルトのオプションメニューを作成し、既存のアイテムを編集するときはそのままにしておきます。 invalidateOptionsMenu()それは新しいアイテムを作成するときです;この場合、メニューをカスタマイズするためにonPrepareOptionsMenu()が自動的にトリガーされます。

たとえば、[オプション]メニューには、既存のアイテムを編集するための削除オプションがあり、新しいアイテムを追加するときにはこれを非表示にする必要があります。

0
Zain
/**
 * Set a hint for whether this fragment's menu should be visible.  This
 * is useful if you know that a fragment has been placed in your view
 * hierarchy so that the user can not currently seen it, so any menu items
 * it has should also not be shown.
 *
 * @param menuVisible The default is true, meaning the fragment's menu will
 * be shown as usual.  If false, the user will not see the menu.
 */
public void setMenuVisibility(boolean menuVisible) {
    if (mMenuVisible != menuVisible) {
        mMenuVisible = menuVisible;
        if (mHasMenu && isAdded() && !isHidden()) {
            mHost.onSupportInvalidateOptionsMenu();
        }
    }
}

XMLメニューサンプル:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto">
<item
    Android:id="@+id/action_edit"
    Android:icon="@drawable/ic_edit"
    Android:title="Edit Task"
    app:showAsAction="always" />

<item
    Android:id="@+id/action_delete"
    Android:icon="@drawable/ic_delete"
    Android:title="Delete Task"
    app:showAsAction="always" />

<item
    Android:id="@+id/action_check"
    Android:icon="@drawable/ic_check"
    Android:title="Check Task"
    app:showAsAction="always" />

<item
    Android:id="@+id/action_uncheck"
    Android:icon="@drawable/ic_undo"
    Android:title="Uncheck Task"
    app:showAsAction="always" />
</menu>

サンプルフラグメント内のコード:

private boolean isMenuItemChecked;

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    setMenuVisibility(false);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.my_menu, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    try {
        menu.findItem(R.id.action_check).setVisible(!isMenuItemChecked);
        menu.findItem(R.id.action_uncheck).setVisible(isMenuItemChecked);
    }
    catch(Exception e) {
        Log.e(TAG, "onPrepareOptionsMenu error");
    }
}

public void loadUi(boolean isMenuItemChecked) {
    this.isMenuItemChecked = isMenuItemChecked;
    setMenuVisibility(true);
}
0

編集:質問に対するより良い答えがあります。

invalidateOptionsMenu()の適切な使用法は、ListViewがあり、MenuItemをすべて削除する場合です。したがって、ListViewが空の場合は、invalidateOptionsMenu()すべて削除MenuItemを削除します。

この回答に関連する質問は次のとおりです。 質問

0
user7086724

フラグメント呼び出しからgetActivity().invalidateOptionsMenu();

0
CoolMind