【问题标题】:How do I hide a menu item in the actionbar?如何在操作栏中隐藏菜单项?
【发布时间】:2012-05-28 09:30:58
【问题描述】:

我有一个带有菜单项的操作栏。如何隐藏/显示该菜单项?

这就是我想要做的:

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

【问题讨论】:

    标签: android android-actionbar menuitem android-menu


    【解决方案1】:

    获取一个指向此类项目的MenuItem,对其调用setVisible 以调整其可见性,然后对您的活动调用invalidateOptionsMenu(),以便相应地调整ActionBar 菜单。

    更新:MenuItem 不是您布局中的常规视图。它有些特别,完全不同。您的代码为item 返回null,这就是导致崩溃的原因。你需要做的是:

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

    这是您应该调用的顺序: 首先调用invalidateOptionsMenu(),然后在onCreateOptionsMenu(Menu) 中获取对MenuItem 的引用(通过调用menu.findItem())并在其上调用setVisible()

    【讨论】:

    • 这是我最初的想法,但这会使应用程序崩溃。
    • @Stir Zoltán:这就是你的做法,如果它使应用程序崩溃,你可能做错了。例如,您的MenuItem 可能是null,因为您使用的是getItem 而不是findItem。如果不查看您的代码和崩溃日志,我们永远不会知道。
    • 好的,但是如何在 onCreateOptionsMenu 方法之外获得对菜单的引用?
    • @Stir Zoltán:我相信你对最后的评论毫无意义......只需在onCreateOptionsMenu 获取对您的菜单项的引用,然后在该点设置项目可见性。或者保留参考,直到您决定它是否应该可见。
    • 我认为(充其量)这个答案措辞不佳,因为步骤顺序错误。正确的顺序是首先调用invalidateOptionsMenu(),然后在onCreateOptionsMenu(Menu) 内部获取对MenuItem 的引用(通过调用menu.findItem())并在其上调用setVisible()。答案by suhas_smby P1r4nh4 给出了正确的方法。
    【解决方案2】:

    找到这个问题的附录:

    如果您想随时更改菜单项的可见性,您只需在活动中设置一个成员变量,以记住您要隐藏菜单并调用 invalidateOptionsMenu() 并隐藏覆盖的 @ 中的项目987654322@方法。

    //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);
        }
    }
    

    在我的示例中,我隐藏了所有项目。

    【讨论】:

    • 这正是我一直在寻找的。握住 MenuItem 并调用 setVisible() 似乎没有达到我的预期(可能是因为我在之后调用了 invalidateOptionsMenu() ,因此重建了菜单),但无论哪种方式 - 这完全符合我的希望,谢谢!
    • 如果您要隐藏每个项目,有一种更简单的方法。而不是在这里循环遍历每个项目,您可以这样做:if (HIDE_MENU) { return false; } else { getSupportMenuInflater().inflate(R.menu.menu_settings, menu); return true; } 文档状态:“您必须返回 true 才能显示菜单;如果返回 false,则不会显示”。
    • 另外,我想提一下,这种方法比公认的答案要干净得多。感谢分享!
    • 通过调用 invalidateOptionMenu() onCreateOptionMenu() 并在 onCreateOptionMenu() 中处理我的条件。谢谢你的好回答
    • onPrepareOptionsMenu() 应该用于显示/隐藏逻辑,而不是 onCreateOptionsMenu(),因为它只被调用一次,所以如果你想在初始化后更改菜单项,它就没有用了。所以在 onCreate 中膨胀,但在 onPrepare 中显示/隐藏。
    【解决方案3】:

    是的。

    1. 您可以设置标志/条件。
    2. 当您想隐藏该选项时,请致电invalidateOptionsMenu()。这将调用onCreateOptionsMenu()
    3. onCreateOptionsMenu() 中,检查标志/条件并显示或 通过以下方式隐藏它:
    MenuItem item = menu.findItem(R.id.menu_Done);
    
    if (flag/condition)) {
      item.setVisible(false); 
    } else { }
    

    【讨论】:

    • 不应该是invalidateOptionsMenu而不是invalidateOptions吗?
    • 如果您将标志设置为布尔值,您可以根据需要将项目的可见性设置为标志(或!标志)。所以,item.setVisbility(!flag);使它成为一个没有 if 条件的单行。
    • 变量“menu”在哪里定义?
    • 它作为参数传递给onCreateOptionsMenu
    • 使用此方法将意味着该项目仍会占用空间,并且您最终可能会在您的 UI 中出现按钮应位于的“间隙”。在 onPrepareOptionsMenu() 中使用 removeItem 就可以了。
    【解决方案4】:

    你可以这样称呼:

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

    更新:

    确保您的代码不会为 item 返回 null,否则可能会导致应用程序崩溃。

    【讨论】:

    • 使用此方法将意味着该项目仍会占用空间,并且您最终可能会在您的 UI 中出现按钮应位于的“间隙”。在 onPrepareOptionsMenu() 中使用 removeItem 就可以了。
    【解决方案5】:

    我一直在寻找更多上下文的答案。现在我已经弄清楚了,我将添加那个答案。

    在菜单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() 刷新菜单。
    【解决方案6】:

    对我不起作用。我必须明确地使用onPrepareOptionsMenu 将项目设置为不可见。

    所以使用onCreateOptionsMenu 创建菜单并使用onPrepareOptionsMenu 更改可见性等。

    【讨论】:

    • 对我来说它是双向的,但基于 Android's docs onPrepareOptionsMenu 似乎是执行此类操作的正确位置:“准备要显示的屏幕的标准选项菜单。这被称为在菜单显示之前,每次显示。您可以使用此方法有效地启用/禁用项目或以其他方式动态修改内容。"
    • 是的,这很理想。 onPrepareOptionsMenu() 应该用于显示/隐藏逻辑,而不是 onCreateOptionsMenu(),因为它只调用一次,因此如果您想在初始化后更改菜单项,它就没有用了。所以在 onCreate 中膨胀,但在 onPrepare 中显示/隐藏,然后使用invalidateOptionsMenu() 刷新菜单。
    【解决方案7】:

    在菜单布局文件中初始设置菜单项可见性为 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 不返回布尔值。不过,该解决方案效果很好。
    【解决方案8】:

    试试这个:

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

    【讨论】:

      【解决方案9】:

      这对 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);
      }
      

      【讨论】:

      • 在我的情况下,onPrepareOptionsMenu 返回布尔值,而不是 void。
      【解决方案10】:

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

      【讨论】:

      • 使用01 不是“布尔标志”,它是伪布尔值。此外,这里没有理由使用实际的布尔值。
      • 另外,您可以有多种状态,而不仅仅是一种隐藏和一种显示。根据您的应用程序的复杂性和您拒绝为新的应用程序状态编写新活动,您可能有 SHOW_ALL 状态、HIDE_ALL 状态,但也有 HIDE_EDIT 或 HIDE_SHARE 状态,以防您想隐藏菜单的某些部分。跨度>
      【解决方案11】:

      根据 Android 开发者官网,不推荐使用 OnCreateOptionMenu(Menu menu) 在运行时更改菜单项或图标、visibility..等。

      系统调用 onCreateOptionsMenu() 后,会保留你填充的 Menu 的一个实例,并且不会再次调用 onCreateOptionsMenu(),除非菜单因某种原因失效。但是,您应该只使用 onCreateOptionsMenu() 来创建初始菜单状态,而不是在活动生命周期中进行更改。

      如果要根据活动生命周期中发生的事件修改选项菜单,可以在 onPrepareOptionsMenu() 方法中进行。此方法向您传递当前存在的 Menu 对象,以便您可以对其进行修改,例如添加、删除或禁用项目。 (片段还提供了一个 onPrepareOptionsMenu() 回调。) --AndroidDeveloper Official Site --

      建议您可以使用此 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(Menu menu) 来更改它们

      @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) 总是可见的项目时,它不会消失,直到我点击三个点(菜单本身)。如果我在onPrepareOptionsMenu 中使用invalidateOptionsMenu(),这些项目会立即自我重组,但它们会失去动作(如果我点击任何项目,它什么也不做)。
      【解决方案12】:

      您可以使用toolbar.getMenu().clear();一次隐藏所有菜单项

      【讨论】:

      • @Ajeet_Yadav 有没有办法在清除菜单后让菜单可见?
      • 调用toolbar.inflateMenu(R.menu.main) 将菜单充气回来
      【解决方案13】:

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

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

      <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 之前执行:

      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       
      }
      

      【讨论】:

        【解决方案14】:

        通过设置Menu中所有项目的Visibility,appbar菜单或溢出菜单会自动隐藏

        例子

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

        【讨论】:

          【解决方案15】:

          给变量赋值并调用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) 总是可见的项目时,它不会消失,直到我点击三个点(菜单本身)。如果我在onPrepareOptionsMenu 中使用invalidateOptionsMenu(),这些项目会立即自我重组,但它们会失去动作(如果我点击任何项目,它什么也不做)。
          【解决方案16】:

          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

          【讨论】:

            【解决方案17】:

            如果您按照上述答案执行了所有操作,但菜单项仍然可见,请检查您是否引用了 unique 资源。 例如,在 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 并检查它是否仅存在于一个菜单文件中。如果此资源已在任何地方使用并加载到活动中,它将尝试隐藏在那里。

            【讨论】:

              【解决方案18】:

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

              【讨论】:

                【解决方案19】:

                对于那些使用 Appcompat 库的用户: 如果你的Activity是ActionBarActivity的子类,你可以调用supportInvalidateOptionsMenu()

                在这里看到: https://stackoverflow.com/a/19649877/1562524

                【讨论】:

                  【解决方案20】:

                  我认为更好的方法是为菜单使用成员变量,在 onCreateOptionsMenu() 中对其进行初始化,然后使用 setVisible(),而不会使选项菜单失效。

                  【讨论】:

                    【解决方案21】:

                    这段代码对我有用

                    @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);
                    }
                    

                    【讨论】:

                      【解决方案22】:

                      这种方法对我有用:

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

                      【讨论】:

                        【解决方案23】:

                        您正在尝试从无权访问范围的活动访问菜单项。查找菜单项的调用将返回 null,因为视图未与 Activity 和布局您正在调用的对象绑定。

                        菜单项与“导航栏”等项绑定,这些项又与相应的活动绑定。

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

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

                        【讨论】:

                          【解决方案24】:

                          使用invalidateOptionsMenu()

                          为了打电话给onPrepareOptionsMenu(menu: Menu?)

                          您应该只使用 onCreateOptionsMenu() 来创建初始菜单状态,而不是在活动生命周期中进行更改...

                          当一个事件发生并且你想要执行一个菜单更新时,你必须调用invalidateOptionsMenu()来请求系统调用onPrepareOptionsMenu()。

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

                          【讨论】:

                            【解决方案25】:

                            这对我有用;希望对你有帮助:

                            @Override
                            public boolean onCreateOptionsMenu(final Menu menu) {
                                getMenuInflater().inflate(R.menu.my_menu_setting, menu);
                            
                                for (int i = 0; i < menu.size(); i++){
                                    if(menu.getItem(i).getItemId() == R.id.this_item_i_want_to_hide){
                                        menu.getItem(i).setVisible(false);
                                    }
                                }
                            
                                return true;
                            }
                            

                            【讨论】:

                              【解决方案26】:

                              以正常方式创建菜单选项,请参见下面的代码,并在类中向菜单添加全局引用

                              Menu mMenu;  // global reference within the class
                              @Override
                              public boolean onCreateOptionsMenu(Menu menu) {
                                  getMenuInflater().inflate(R.menu.menu_tcktdetails, menu);
                                  mMenu=menu;  // assign the menu to the new menu item you just created 
                                  return true;
                              }
                              
                              
                              @Override
                              public boolean onOptionsItemSelected(MenuItem item) {
                                  int id = item.getItemId();
                                  if (id == R.id.action_cancelticket) {
                                      cancelTicket();
                              
                                      return true;
                                  }
                              
                                  return super.onOptionsItemSelected(item);
                              }
                              

                              现在您可以通过使用按钮或在函数中运行此代码来切换菜单

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

                              【讨论】:

                                猜你喜欢
                                • 1970-01-01
                                • 2013-12-18
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 2013-04-13
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                相关资源
                                最近更新 更多