アクションバーのメニュー項目を非表示にするにはどうすればよいですか?


346

メニューアイテムのあるアクションバーがあります。そのメニュー項目をどのように非表示/表示できますか?

これは私がやろうとしていることです:

MenuItem item = (MenuItem) findViewById(R.id.addAction);
item.setVisible(false);
this.invalidateOptionsMenu();

回答:


484

MenuItemそのようなアイテムへのポイントを取得し、setVisibleそれを呼び出して可視性を調整してから、invalidateOptionsMenu()、アクティビティをて、それに応じてActionBarメニューを調整します。

更新: A MenuItemは、レイアウトの一部である通常のビューではありません。その特別な何か、完全に異なる。あなたのコードが戻ってきnullitem、それがクラッシュの原因です。代わりにあなたがする必要があるのは:

MenuItem item = menu.findItem(R.id.addAction);

最初の呼び出しを:ここでは、呼び出す必要があります順序でinvalidateOptionsMenu()、その後の内部onCreateOptionsMenu(Menu)(呼び出すことでのMenuItemへの参照を取得menu.findItem())と呼んでsetVisible()、それには、


これは私が最初に考えたものですが、これはアプリケーションをクラッシュさせます。
ゾルタンを

3
@StirZoltán:そうですね、それがあなたのやり方です。もしそれがアプリケーションをクラッシュさせたら、あなたはそれを間違っているかもしれません。たとえば、の代わりにを使用しているMenuItemことがnull原因である可能性がgetItemありfindItemます。私たちはあなたのコードとクラッシュログの両方を見なければ、決して知ることができませんでした。
K-ballo

わかりましたが、onCreateOptionsMenuメソッドの外でメニューへの参照を取得するにはどうすればよいですか?
炒めゾルタン

7
@StirZoltán:最後のコメントでは意味が分からないと思います...でメニュー項目への参照を取得し、onCreateOptionsMenuその時点で項目の可視性を設定してください。または、表示するかどうかを決定するまで参照を維持します。
K-ballo

33
ステップのシーケンスが間違っているため、私は(せいぜい)この答えは不適切な言葉遣いだと思います。正しいシーケンスは、最初に呼び出しinvalidateOptionsMenu()、次に内部で(を呼び出すことにより)onCreateOptionsMenu(Menu)への参照を取得して呼び出すことです。suhas_smP1r4nh4 による回答は、正しいアプローチを示しています。MenuItemmenu.findItem()setVisible()
テッド・ホップ2014年

163

この質問の補遺が見つかりました:

外出先でメニュー項目の可視性を変更する場合は、アクティビティにメンバー変数を設定して、メニューinvalidateOptionsMenu()を非表示にし、オーバーライドされたonCreateOptionsMenu(...)メソッドで項目を呼び出して非表示にすることを覚えておく必要があります。

//anywhere in your code
...
mState = HIDE_MENU; // setting state
invalidateOptionsMenu(); // now onCreateOptionsMenu(...) is called again
...

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    // inflate menu from xml
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.settings, menu);

    if (mState == HIDE_MENU)
    {
        for (int i = 0; i < menu.size(); i++)
            menu.getItem(i).setVisible(false);
    }
}

私の例では、すべてのアイテムを非表示にしています。


2
これはまさに私が探していたものです。MenuItemを押したままsetVisible()を呼び出すと、期待どおりに動作しなかったようです(多分、後でinvalidateOptionsMenu()を呼び出したため、メニューを再構築したため)。
Matt

4
すべてのアイテムを非表示にする場合は、もっと簡単な方法があります。ここで各項目をループする代わりに、次のようにすることができます。if (HIDE_MENU) { return false; } else { getSupportMenuInflater().inflate(R.menu.menu_settings, menu); return true; }ドキュメントの状態:「メニューを表示するにはtrueを返す必要があります。falseを返すと表示されません」。
w3bshark 2016年

また、私はこのアプローチが受け入れられた答えよりもはるかにきれいであることを述べたいと思います。共有してくれてありがとう!
w3bshark

invalidateOptionMenu()を呼び出してonCreateOptionMenu()を呼び出し、onCreateOptionMenu()で条件を処理します。良い答えをありがとう
user1912026

onPrepareOptionsMenu()onCreateOptionsMenu()一度だけ呼び出されるので、表示/非表示ロジックに使用する必要がある ため、初期化後にメニュー項目を変更する場合は役に立ちません。したがって、onCreateではインフレートしますが、onPrepareでは表示/非表示にします。
JCutting8

89

はい。

  1. フラグ/条件を設定できます。
  2. invalidateOptionsMenu()オプションを非表示にしたいときに呼び出します。これはを呼び出しますonCreateOptionsMenu()
  3. ではonCreateOptionsMenu()フラグ/条件および表示または非表示にするためのチェック次の方法:
MenuItem item = menu.findItem(R.id.menu_Done);

if (flag/condition)) {
  item.setVisible(false); 
} else { }

2
invalidateOptionsMenu代わりにすべきではありませんinvalidateOptionsか?
ラズ

3
フラグをブール値にした場合、必要に応じてアイテムの可視性をフラグ(または!flag)に設定できます。したがって、item.setVisbility(!flag); これは、if条件のない1つのライナーになります。
jwehrle

変数「メニュー」はどこに定義されていますか?
ジョナサン

パラメータとして渡されますonCreateOptionsMenu
suhas_sm

このメソッドを使用すると、アイテムがまだスペースを消費し、ボタンのある場所にUIで「ギャップ」が生じる可能性があります。onPrepareOptionsMenu()でremoveItemを使用するとうまくいきます。
JCutting8

39

あなたはこれを呼び出すことができます:

MenuItem item = menu.findItem(R.id.my_item);
item.setVisible(false);

更新:

あなたのコードが返されていないことを確認しますnullためitemか、アプリケーションをクラッシュすることがあります。


このメソッドを使用すると、アイテムがまだスペースを消費し、ボタンのある場所にUIで「ギャップ」が生じる可能性があります。onPrepareOptionsMenu()でremoveItemを使用するとうまくいきます。
JCutting8

33

もう少し前後関係のある答えを探していました。私はそれを理解したので、その答えを追加します。

メニューxmlのデフォルトでボタンを非表示

で設定されてandroid:visible="false"いるように、デフォルトでは共有ボタンは非表示になります。

ここに画像の説明を入力してください

main_menu.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">

    <!-- hide share button by default -->
    <item
        android:id="@+id/menu_action_share"
        android:icon="@drawable/ic_share_white_24dp"
        android:visible="false"     
        android:title="Share"
        app:showAsAction="always"/>

    <item
        android:id="@+id/menu_action_settings"
        android:icon="@drawable/ic_settings_white_24dp"
        android:title="Setting"
        app:showAsAction="ifRoom"/>

</menu>

コードにボタンを表示

ただし、共有ボタンは、状況に応じてオプションで表示できます。

ここに画像の説明を入力してください

MainActivity.java

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);
    MenuItem shareItem = menu.findItem(R.id.menu_action_share);

    // show the button when some condition is true
    if (someCondition) {        
        shareItem.setVisible(true);
    }

    return true;
}

こちらもご覧ください

  • アプリバーの設定(アプリ/アクションバーの設定に関するヘルプのAndroidドキュメント)

onCreateOptionsMenu()ではなくonPrepareOptionsMenu()を表示/非表示ロジックに使用する必要があります。これは一度だけ呼び出されるため、初期化後にメニュー項目を変更する場合は役に立ちません。したがって、onCreateでインフレートしますが、onPrepareで表示/非表示にしてから、を使用invalidateOptionsMenu()してメニューを更新します。
JCutting8

24

うまくいきませんでした。onPrepareOptionsMenuアイテムを非表示にするには、明示的に使用する必要がありました。

したがってonCreateOptionsMenu、メニューの作成やonPrepareOptionsMenu可視性の変更などに使用します。


1
私にとっては両方の方法で機能しましたが、Androidのドキュメントに 基づいて、onPrepareOptionsMenuこのタイプの操作を行うのに適切な場所のように思われます。このメソッドを使用すると、アイテムを効率的に有効/無効にしたり、コンテンツを動的に変更したりできます。」
yuval

はい、これは理想的です。onCreateOptionsMenu()ではなくonPrepareOptionsMenu()を表示/非表示ロジックに使用する必要があります。これは一度だけ呼び出されるため、初期化後にメニュー項目を変更する場合は役に立ちません。したがって、onCreateでインフレートしますが、onPrepareで表示/非表示にしてから、を使用invalidateOptionsMenu()してメニューを更新します。
JCutting8

9

以下のように、最初にメニューレイアウトファイルでメニュー項目の可視性をfalseに設定します。

<?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:visible="false"
        android:id="@+id/action_do_something"
        android:title="@string/txt_do_something"
        app:showAsAction="always|withText"
        android:icon="@drawable/ic_done"/>
</menu>

次に、メニューを拡張した後、onCreateOptionsMenu()でメニュー項目の可視性をfalseに設定するだけです。

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(menu,R.menu.menu);
    MenuItem item = menu.findItem(R.id.menuItemId);
    if (item != null){
        item.setVisible(false);
    }
}

onCreateOptionsMenuはブール値を返しません。しかし、このソリューションは完全に機能しました。
ジョセフ


7

これは、アクティビティとフラグメントの両方から私のために働きました

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    if (menu.findItem(R.id.action_messages) != null)
        menu.findItem(R.id.action_messages).setVisible(false);
}

1
私の場合、onPrepareOptionsMenuはvoidではなくbooleanを返します。
CoolMind 2016

6

P1r4nh4の回答は問題なく機能します。ブールフラグを使用して単純化しました。

public int mState = 0; //at the top of the code
//where you want to trigger the hide action
mState = 1; // to hide or mState = 0; to show
invalidateOptionsMenu(); // now onCreateOptionsMenu(...) is called again
...

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    // inflate menu from xml
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.settings, menu);

    if (mState == 1) //1 is true, 0 is false
    {
        //hide only option 2
            menu.getItem(2).setVisible(false);
    }
}

2
を使用して0おり1、「ブールフラグ」ではなく、疑似ブールです。さらに、実際のブール値をここで使用する理由はありません。
IngoBürk2013

2
また、1つだけを非表示にして1つを表示するだけでなく、いくつかの状態を設定することもできます。アプリの複雑さと新しいアプリの状態に対して新しいアクティビティを書き込むことを拒否することによって、SHOW_ALL状態、HIDE_ALL状態になる可能性がありますが、メニューの特定の部分を非表示にする場合は、HIDE_EDITまたはHIDE_SHARE状態になることもあります。
P1r4nh4 2013

4

Android Developer Officialのサイトによると、OnCreateOptionMenu(メニューメニュー)は、実行時にメニュー項目やアイコン、visibility..etcを変更することは推奨されていません。

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

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

推奨通りこのonOptionsItemSelected(MenuItem item)メソッドを使用して、ユーザー入力を追跡できます。

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();

    if (id == R.id.edit) {
        Intent intent = new Intent(this, ExampleActivity.class);
        intent.putExtra(BUNDLE_KEY, mConnection);
        startActivityForResult(intent, PICK_CHANGE_REQUEST);
        return true;
    } else if (id == R.id.delete) {
        showDialog(this);
        return true;
    }

    return super.onOptionsItemSelected(item);
}

実行時にメニュー項目を変更する必要がある場合は、onPrepareOptionsMenu(メニューメニュー)を使用して変更できます。

@Override
public boolean onPrepareOptionsMenu(Menu menu){

    if (Utils.checkNetworkStatus(ExampleActivity.this)) {
        menu.findItem(R.id.edit).setVisible(true);
        menu.findItem(R.id.delete).setVisible(true);
    }else {
        menu.findItem(R.id.edit).setVisible(false);
        menu.findItem(R.id.delete).setVisible(false);
    }
    return true;
} 

一部のアイテムは常に表示さsetVisible(false)れているため、常に表示されるアイテムの場合は、3つのドット(メニュー自体)をクリックするまで消えません。アイテムで使用するinvalidateOptionsMenu()onPrepareOptionsMenuすぐに再編成されますが、アクションは失われます(アイテムをクリックしても何も起こりません)。
Aliton Oliveira

3

変数に値を設定し、invalidateOptionsMenu();を呼び出します。

例えば

    selectedid=arg2;
            invalidateOptionsMenu();


 public boolean onPrepareOptionsMenu(Menu menu) {

    if(selectedid==1){
        menu.findItem(R.id.action_setting).setVisible(false);
        menu.findItem(R.id.action_s2).setVisible(false);
        menu.findItem(R.id.action_s3).setVisible(false);
    }
    else{
        if(selectedid==2){
            menu.findItem(R.id.action_search).setVisible(false);
            menu.findItem(R.id.action_s4).setVisible(false);
            menu.findItem(R.id.action_s5).setVisible(false);
        }
    }
    return super.onPrepareOptionsMenu(menu);
}

一部のアイテムは常に表示さsetVisible(false)れているため、常に表示されるアイテムの場合は、3つのドット(メニュー自体)をクリックするまで消えません。アイテムで使用するinvalidateOptionsMenu()onPrepareOptionsMenuすぐに再編成されますが、アクションは失われます(アイテムをクリックしても何も起こりません)。
Aliton Oliveira

3

を使用toolbar.getMenu().clear();して、一度にすべてのメニュー項目を非表示にすることができます


@Ajeet_Yadavは、メニューをクリアした後にメニューを表示する方法はありますか?
Shawn、

3

メニューのすべてのアイテムの表示を設定すると、アプリバーメニューまたはオーバーフローメニューが自動的に非表示になります

private Menu menu_change_language;

...

...

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    ...
    ...
    menu_change_language = menu;
    menu_change_language.findItem(R.id.menu_change_language)
           .setVisible(true);

    return super.onCreateOptionsMenu(menu);
}

他のフラグメントに進む前に、次のコードを使用します。

if(menu_change_language != null){                 
    menu_change_language.findItem(R.id.menu_change_language)
       .setVisible(false);
}

2

https://stackoverflow.com/a/21215280/466363-Look AlternoおよびSufianによる回答

  • ActivityCompat.invalidateOptionsMenu()はonPrepareOptionsMenu();をコールバックしません。メニューを直接更新するだけです。
  • 私のsomeMethod()は、onCreateOptionsMenu()の前でも、いくつかの場所から呼び出されるため、mMenu!= nullを確認する必要があります。
  • API 8を使用して動作するはずです

private Menu mMenu;
   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
       inflater.inflate(R.menu.track_fragment, menu);
       mMenu = menu;
       }
   ...
   private void someMethod() {
   ...
       if (mMenu != null) {
          MenuItem item = mMenu.findItem(R.id.new_track);
          if (item != null) {
               item.setVisible(false);
               ActivityCompat.invalidateOptionsMenu(this.getActivity());
           }
       }
   ...
   }
  • ActivityCompat.invalidateOptionsMenu()はonPrepareOptionsMenu();をコールバックしません。メニューを直接更新するだけです。

  • 私のsomeMethod()は、onCreateOptionsMenu()の前でも、いくつかの場所から呼び出されるため、mMenu!= nullを確認する必要があります。

  • API 8を使用して動作するはずです

2

上記の回答のようにすべてを実行してもメニュー項目が表示されている場合は、一意のリソースを参照していることを確認してください。たとえば、onCreateOptionsMenuまたはonPrepareOptionsMenu

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    MenuItem menuOpen = menu.findItem(R.id.menu_open);
    menuOpen.setVisible(false);
}

Ctrlキーを押しながらR.id.menu_openをクリックし、1つのメニューファイルにのみ存在することを確認します。このリソースがすでにどこかで使用されており、アクティビティに読み込まれている場合、そのリソースを非表示にしようとします。


2

1つのコマンドだけでメニューのすべての項目を非表示にする最良の方法は、メニューxmlで「グループ」を使用することです。同じグループ内のオーバーフローメニューに含まれるすべてのメニュー項目を追加するだけです。

この例では、常に表示される2つのメニュー項目(通常の項目と検索)と3つのオーバーフロー項目があります。

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/someItemNotToHide1"
        android:title="ITEM"
        app:showAsAction="always" />

    <item
        android:id="@+id/someItemNotToHide2"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="collapseActionView|ifRoom"
        app:actionViewClass="android.support.v7.widget.SearchView"
        android:title="Search"/>

    <group android:id="@+id/overFlowItemsToHide">
    <item android:id="@+id/someID" 
    android:orderInCategory="1" app:showAsAction="never" />
    <item android:id="@+id/someID2" 
    android:orderInCategory="1" app:showAsAction="never" />
    <item android:id="@+id/someID3" 
    android:orderInCategory="1" app:showAsAction="never" />
    </group>
</menu>

次に、アクティビティ(onCreateOptionsMenuで推奨)で、コマンドsetGroupVisibleを使用して、すべてのメニュー項目の可視性をfalseまたはtrueに設定します。

public boolean onCreateOptionsMenu(Menu menu) {
   menu.setGroupVisible(R.id.overFlowItems, false); // Or true to be visible
}

アクティビティの他の場所でこのコマンドを使用する場合は、必ずメニュークラスをローカルに保存し、createOptionsMenuの前に実行できるため、常にメニューがnullかどうかを確認してください。

Menu menu;

public boolean onCreateOptionsMenu(Menu menu) {
       this.menu = menu;

}

public void hideMenus() {
       if (menu != null) menu.setGroupVisible(R.id.overFlowItems, false); // Or true to be visible       
}


1

メニューのメンバー変数を使用し、onCreateOptionsMenu()で初期化し、後でオプションメニューを無効にせずにsetVisible()を使用するのが、より良いアプローチだと思います。


1

このコードは私のために働きました

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu,menu);
    if (Application.sharedPreferences.getInt("type",1) == 2)
    {
        menuItem = menu.findItem(R.id.menu_travel_orders);
        menuItem.setVisible(false);
    }
    return super.onCreateOptionsMenu(menu);
}

1

このアプローチは私にとってうまくいきました:

private  Menu thismenu;

if (condition)
{
   if(thismenu != null)
   {
       thismenu.findItem(R.id.menu_save).setVisible(true);
       Toast.makeText(ProfileActivity.this, 
    ""+thismenu.findItem(R.id.menu_save).getTitle(),
                Toast.LENGTH_SHORT).show();
   }else
   {
       thismenu.findItem(R.id.menu_save).setVisible(false);
   }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
   getMenuInflater().inflate(R.menu.profile_menu, menu);
   thismenu = menu;

   return true;
}

1

スコープにアクセスできないアクティビティからメニュー項目にアクセスしようとしています。メニュー項目を検索する呼び出しはnullを返します。これは、ビューが呼び出し元のアクティビティまたはレイアウトのどちらにもバインドされていないためです。

メニュー項目は、「ナビゲーションバー」などの項目にバインドされ、次に対応するアクティビティにバインドされます。

したがって、アクティビティ()でこれらのビューを初期化し、そのビューを使用してメニュー項目にアクセスします。

Navigation navView;
navView = findViewById(R.id.navigationView);

MenuItem item = navView.getMenu().findItem(R.id.item_hosting);
item.setVisible(false);

1

使用する invalidateOptionsMenu()

呼び出すために onPrepareOptionsMenu(menu: Menu?)

onCreateOptionsMenu()は、初期メニュー状態を作成するためにのみ使用し、アクティビティのライフサイクル中に変更を加えないでください...

イベントが発生してメニューの更新を実行したい場合は、invalidateOptionsMenu()を呼び出して、システムがonPrepareOptionsMenu()を呼び出すように要求する必要があります。

https://developer.android.com/guide/topics/ui/menus


0

Android kotlin、アクションバーのメニュー項目の可視性をプログラムで非表示または設定。

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    val inflater = menuInflater
    inflater.inflate(R.menu.main_menu, menu)
    val method = menu.findItem(R.id.menu_method)
    method.isVisible = false //if want to show set true
    return super.onCreateOptionsMenu(menu)
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.