如何在操作栏中隐藏菜单项?


Answers:


484

获取一个MenuItem指向这样的项目,调用setVisible它来调整其知名度,然后调用invalidateOptionsMenu()所以动作条菜单进行相应的调整你的活动。

更新: A MenuItem不是常规视图,它是布局的一部分。它与众不同,完全不同。您的代码返回nullitem导致崩溃。您需要做的是:

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

下面是你应该调用顺序:先调用invalidateOptionsMenu(),然后里面onCreateOptionsMenu(Menu)获得的菜单项的引用(通过调用menu.findItem()),并调用setVisible()就可以了


这是我最初想到的,但是这会使应用程序崩溃。
StirZoltán2012年

3
@StirZoltán:就是这样,如果它使应用程序崩溃,则可能做错了。例如,您MenuItem可能是null因为您使用getItem而不是findItem。我们永远不会知道,而没有看到您的代码和崩溃日志。
K-ballo 2012年

可以,但是如何在onCreateOptionsMenu方法之外获取对菜单的引用?
搅拌佐尔坦

7
@StirZoltán:我相信您对最后一条评论毫无意义...只需在处获取对菜单项的引用onCreateOptionsMenu,然后在该点设置项的可见性即可。或者保留参考,直到您决定是否应该看到它。
K-ballo 2012年

33
我认为(充其量)此答案措辞不佳,因为步骤顺序错误。正确的顺序是先调用invalidateOptionsMenu(),然后在内部onCreateOptionsMenu(Menu)获取对的引用MenuItem(通过调用menu.findItem())并对其进行调用setVisible()suhas_smP1r4nh4的答案提出了正确的方法。
泰德·霍普

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(),从而重新构建了菜单),但是无论哪种方式-这与我希望的完全一样,谢谢!
马特

4
如果您要隐藏每个项目,则有一种更简单的方法。您可以执行以下操作,而不是遍历这里的每个项目:if (HIDE_MENU) { return false; } else { getSupportMenuInflater().inflate(R.menu.menu_settings, menu); return true; }docs状态:“要显示的菜单必须返回true;如果返回false,则不会显示”。
w3bshark

另外,我想提一下,这种方法比公认的答案要干净得多。感谢分享!
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
razz 2015年

3
如果将标志设为布尔值,则可以根据需要将项目的可见性设置为标志(或!flag)。因此,item.setVisbility(!flag); 使它成为一个无条件的衬里。
jwehrle's

变量“菜单”在哪里定义?
乔纳森

它作为参数传递给onCreateOptionsMenu
suhas_sm

使用此方法将意味着该项目仍会占用空间,并且您最终可能在用户界面中应有按钮的地方出现“空白”。在onPrepareOptionsMenu()中使用removeItem可以解决问题。
JCutting8

39

您可以这样称呼:

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

更新:

确保您的代码没有返回nullitem否则可能会使应用程序崩溃。


使用此方法将意味着该项目仍会占用空间,并且您最终可能在用户界面中应有按钮的地方出现“空白”。在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;
}

也可以看看


onPrepareOptionsMenu()应该用于显示/隐藏逻辑,而不是onCreateOptionsMenu(),因为它仅被调用一次,因此如果要在初始化后更改菜单项,则没有用。因此,在onCreate中充气,但在onPrepare中显示/隐藏,然后用于invalidateOptionsMenu()刷新菜单。
JCutting8

24

没有为我工作。我必须明确使用onPrepareOptionsMenu将项目设置为不可见。

因此,用于onCreateOptionsMenu创建菜单和onPrepareOptionsMenu更改可见性等。


1
对我来说,这两种方法都是可行的,但是基于Android的文档, onPrepareOptionsMenu似乎是进行此类操作的正确位置:“准备要显示的屏幕标准选项菜单。每次显示菜单时都会调用此菜单。您可以使用此方法有效地启用/禁用项目,或以其他方式动态地修改内容。”
yuval 2015年

是的,这很理想。onPrepareOptionsMenu()应该用于显示/隐藏逻辑,而不是onCreateOptionsMenu(),因为它仅被调用一次,因此如果要在初始化后更改菜单项,则没有用。因此,在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

这从Activity和Fragment都对我有用

@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。
CoolMind '16

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
使用01不是“布尔标志”,它是伪布尔。此外,这里没有理由使用实际的布尔值。
IngoBürk'13

2
另外,您可能有几种状态,不仅要隐藏一种状态,还要显示一种状态。根据您应用程序的复杂性以及您拒绝为新应用程序状态编写新活动的情况,您可能会具有SHOW_ALL状态,HIDE_ALL状态以及HIDE_EDIT或HIDE_SHARE状态,以防您要隐藏菜单的某些部分。
P1r4nh4 2013年

4

根据Android开发人员官方网站的说法,建议不要在运行时更改菜单项或图标,可见性等来推荐OnCreateOptionMenu(菜单菜单)。

系统调用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)选择始终可见的项目时,直到单击三个点(菜单本身)后,该项目才会消失。如果我invalidateOptionsMenu()onPrepareOptionsMenu项目中使用,则立即对其进行自我重组,但它们会松开动作(如果我单击任何项​​目,则不会执行任何操作)。
阿里顿·奥利维拉

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)选择始终可见的项目时,直到单击三个点(菜单本身)后,该项目才会消失。如果我invalidateOptionsMenu()onPrepareOptionsMenu项目中使用,则立即对其自身进行重组,但它们会松开动作(如果我单击任何项​​目,则不会执行任何操作)。
阿里顿·奥利维拉


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并检查它是否仅存在于一个菜单文件中。如果此资源已在任何地方使用并加载到活动中,它将尝试隐藏在那里。


2

仅用一个命令隐藏菜单中所有项目的最好方法是在菜单xml中使用“ group”。只需在同一组内的溢出菜单中添加所有菜单项即可。

在此示例中,我们将始终显示两个菜单项(常规项和搜索)和三个溢出项:

<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
}

如果要在活动的其他任何地方使用此命令,请确保将菜单类保存到本地,并始终检查menu是否为null,因为可以在createOptionsMenu之前执行:

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

这段代码对我有用

@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,因为视图既未绑定活动,也未绑定布局您要从其调用。

菜单项与诸如“ 导航栏 ”之又与相应的活动绑定。

因此,请在activity()中初始化这些视图,然后使用该视图访问菜单项。

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

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


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)
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.