ActionBarに表示されるメニュー項目を更新する方法は?


93

2つのフラグメントを持つアクティビティがあります。どちらもListFragmentsであり、MenuItemsをMenuに提供します。ActionBarのボタンとして表示するためにandroid:showAsAction属性を設定した1つのMenuItemがあります。うまくいきます。

現在、MenuItemは状態に依存しています。これは、キューを一時停止および再開するための一時停止/再開メニューオプションです。私の問題は、フラグメントが作成されたときの初期像の設定方法がわからないことです。

その状態は、キューが一時停止されているかどうかによって異なります。したがって、キューを取得し、キューの状態に基づいてブール値(一時停止)を設定するAsyncTaskがあります。onPrepareOptionsMenuを呼び出して、キューの最後の既知の状態に基づいて一時停止メニュー項目のテキストを設定します。これは、実際のメニューにMenuItemを残しておくとうまく機能します。メニューアイコンをタップすると、onPrepareOptionsMenuが起動し、メニューが表示される前に更新されます。

問題は、同じMenuItemをActionBar(showAsAction)に配置した場合、onPrepareOptionsMenuを呼び出さずに強制的に更新する方法です。アプリを初めて起動したときに、キューを取得するリクエストを送信しましたが、ActionBarがセットアップされて表示された後にタスクが戻るため、これを実行できるようにする必要があります。キューの更新を取得するたびに呼び出されるハンドラーをフラグメントに作成しましたが、そこから、ActionBarのMenuItemのテキストをどのように更新できますか?onPrepareOptionMenuを除いて、現在設定されているメニューを操作する方法を見つけることができないようです。

ロブ・W

回答:


174

オプション#1:をお試しくださいinvalidateOptionsMenu()。これによってアクションバーが即座に再描画されるかどうかはわかりません。

オプション#2:getActionView()影響を受けるに対して何かが返されるかどうかを確認しますMenuItemshowAsAction単純に自動的にアクションビューを作成することが可能です。もしそうなら、おそらくそれを有効/無効にすることができますView

onPrepareOptionMenuを除いて、現在設定されているメニューを操作する方法を見つけることができないようです。

Menu渡されたオブジェクトにぶら下がることができますonCreateOptionsMenu()ドキュメントの引用:

次にonCreateOptionsMenu()が呼び出されるまで、メニュー(およびメニューから作成されたアイテム)を安全に保持し、必要に応じてメニューを変更できます。


2
オプション#1を試しましたが、これでうまくいきました。別のスレッドからのコールバックでUIを更新しようとしていたため、実際にはUIスレッド上にいなかったため、例外がスローされていました。これを修正するために、ハンドラーを作成し、コールバックが呼び出されたときに更新メッセージをハンドラーに送信しました。しかし、最終的にはgetActivity()。invalidateOptionsMenu()を使用してメニューを更新しました。
brockoli

@brockoli:ああ、いいね!そのメソッドのJavadocの言い回しを考えると、私がAPIレベル11に最初に追加した理由であるように思われたとしても、それが望ましい効果をもたらすかどうかは疑問でした。それがあなたのために働いていると聞いてうれしい!
CommonsWare 2011

私はこれを理解しようとして壁に頭をぶつけてきました、それは魅力のように機能します!
MinceMan 2012

7
サポートライブラリを使用している場合は、supportInvalidateOptionsMenu()代わりに使用してください
Tim Kist

2
@TimKist supportInvalidateOptionsMenu()は非推奨になりました。安全に使用できますinvalidateOptionsMenu()
プリモジュKralj

12

私の場合:invalidateOptionsMenuテキストを元のテキストに再設定するだけで、メニュー項目に直接アクセスして希望のテキストを書き直すと、問題なく機能しました。

if (mnuTopMenuActionBar_ != null) {
    MenuItem mnuPageIndex = mnuTopMenuActionBar_
        .findItem(R.id.menu_magazin_pageOfPage_text);

    if (mnuPageIndex != null) {
        if (getScreenOrientation() == 1) {
            mnuPageIndex.setTitle((i + 1) + " von " + pages);
        }
        else {
            mnuPageIndex.setTitle(
                (i + 1) + " + " + (i + 2) + " " + " von " + pages);
        }
        // invalidateOptionsMenu();
    }
}

以下のコメントにより、次のコードを使用してメニュー項目にアクセスできました。

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.magazine_swipe_activity, menu);
    mnuTopMenuActionBar_ = menu;
    return true;
}

どのようにしてActionBarビューへのハンドルを取得しましたmnuTopMenuActionBar_か?
Paul Mennega、2012年

1
アクションバーが初期化されると、ビューをメンバー変数に保存しました...このように:@Override public boolean onCreateOptionsMenu(Menu menu){MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.magazine_swipe_activity、menu); mnuTopMenuActionBar_ =メニュー; trueを返します。}
cV2 2012年

そうすることで、同期の問題が発生する可能性がありますか?というのは。onCreateOptionMenuが実行されるときに正確にわからないので、mnuTopMenuActionBar_初期化されていない状態でコードに到達することがありますよね?それをどのように回避しますか?
acrespo 2013年

ちょっと、アクションバーがなるように...(直接活動の開始時)には問題ありません、このメソッドは常に呼び出された(はい、ここにある)を使用する場合stackoverflow.com/questions/7705927/...は
CV2

11

Fragmentからメニューを更新するには、次を呼び出します。

getActivity().invalidateOptionsMenu();

4

私はこのコードを使用しました:

public boolean onPrepareOptionsMenu (Menu menu) {       
    MenuInflater inflater = getMenuInflater();
    TextView title  = (TextView) findViewById(R.id.title);
    menu.getItem(0).setTitle(
        getString(R.string.payFor) + " " + title.getText().toString());
    menu.getItem(1).setTitle(getString(R.string.payFor) + "...");
    return true;        
}

そして私にとって魅力のように働いたあなたはここで OnPrepareOptionsMenuを見つけることができます


4
ここでMenuInflaterの目的は何ですか?
IgorGanapolsky 2013年

これはすばらしい
スティーブカマウ

2

最初に、2行のコードに従ってアクションバー項目を更新してから、oncreateOptionMenu()で条件を設定してください。例えば:

Boolean mISQuizItemSelected = false;

/**
 * Called to inflate the action bar menus
 *
 * @param menu
 *      the menu
 *
 * @return true, if successful
 */

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu items for use in the action bar

    inflater.inflate(R.menu.menu_demo, menu);

    //condition to hide the menus
    if (mISQuizItemSelected) {
        for (int i = 0; i < menu.size(); i++) {
            menu.getItem(i).setVisible(false);
        }
    }

    return super.onCreateOptionsMenu(menu);
}

/**
 * Called when the item on the action bar being selected.
 *
 * @param item
 *      menuitem being selected
 *
 * @return true if the menuitem id being selected is matched
 * false if none of the menuitems id are matched
 */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getId() == R.id.action_quiz) {
        //to navigate based on the usertype either learner or leo
        mISQuizItemSelected = true;

        ActionBar actionBar = getActionBar();
        invalidateOptionMenu();
    }
}

1

明確にするために、私はリソースをつかむ直接の例を以下から示すことができると思いました。簡単な直接の例でこの質問の回答に貢献すると思います。

private MenuItem menuItem_;

@Override
public boolean onCreateOptionsMenu(Menu menuF) 
{
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_layout, menuF);
    menuItem_ = menuF.findItem(R.id.menu_item_identifier);
    return true;
}

この場合、最初にMenuItem参照を保持し、後で特定の時点でその状態を変更します(たとえば、アイコンの状態の変更の場合)。


-1

Kotlin 1.2単に呼び出します。

invalidateOptionsMenu()

そして、onCreateOptionsMenu関数は再び呼び出されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.