为不同的片段隐藏/显示操作栏选项菜单项

65

我有一个Sherlock Fragment Activity,在其中有3个Fragment。

Fragment A,Fragment B,Fragment C是三个片段。我想在Fragment B中显示一个完成的选项菜单。

并且活动是从Fragment A开始的。选择Fragment B时,将添加完成按钮。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    if(!menusInflated){
        inflater.inflate(R.menu.security, menu);
        menusInflated=true;
    }

    super.onCreateOptionsMenu(menu, inflater);
}

当我再次开始Fragment A时,我希望为此设置在Fragment B中的选项菜单“完成”(DONE),我的操作如下:

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

但这并不是隐藏,而且当Activity与Fragment A一起首次启动时会引发NullPointerException异常。

请告诉我问题出在哪里。


你解决了这个问题吗?我也遇到了同样的问题。谢谢。 - user3383415
3
这个问题与你遇到的问题不一致。你不需要从操作栏中“隐藏”按钮,而是需要确保操作栏选项在不同的片段中正确加载。在每个onCreateOptionsMenu()函数中,使用menu.clear()清除菜单,在填充菜单之前,这将删除其中的任何旧选项。 - C0D3LIC1OU5
1
只是为了澄清,在您的情况下,您需要在Fragment A中使用空/默认菜单覆盖onCreateOptionsMenu()(并使用menu.clear())。您可能还需要为Fragment C执行此操作。手动确保ActionBar菜单在片段中正常工作是使用片段显示内容的代价,而不是使用活动。 - C0D3LIC1OU5
如果下面的任何答案对您有所帮助,请记得将其接受为解决方案。 - C0D3LIC1OU5
13个回答

115

试试这个...

你不需要再次在你的Fragment类中重写onCreateOptionsMenu()方法。可以通过重写Fragment类中可用的onPrepareOptionsMenu()方法来更改菜单项的可见性。

 @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
    menu.findItem(R.id.action_search).setVisible(false);
    super.onPrepareOptionsMenu(menu);
}

1
最适合我的!这应该是被接受的答案。 - Tanuj Dhaundiyal
我正在尝试从AppCompatActivity派生的活动中调用此表单,但setHasOptionsMenu()方法无法解析。 - techtinkerer
@techtinkerer:你应该在Fragment中重写这些方法,这些方法覆盖了父Activity中的onCreateOptionsMenu()。 - Silambarasan Poonguti
1
我必须在所有我想要隐藏图标的片段中的onViewCreated中添加setHasOptionsMenu(true)。有没有办法只写一次setHasOptionsMenu,并在覆盖onPrepareOptionsMenu的任何片段上隐藏图标? - gegobyte
@Chinmay Sarupria,是的,你可以!创建一个BaseFragment并在该片段中执行此操作,然后将其扩展到您想要隐藏的子片段上。 - Silambarasan Poonguti

77

这是一种做法:

在菜单中添加一个“组”:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <group
        android:id="@+id/main_menu_group">
         <item android:id="@+id/done_item"
              android:title="..."
              android:icon="..."
              android:showAsAction="..."/>
    </group>
</menu>
Menu menu;

将变量添加到您的活动中,并在重写onCreateOptionsMenu方法时进行设置:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    this.menu = menu;
    // inflate your menu here
}

在此之后,将此函数添加到您的活动中,以便在需要显示/隐藏菜单时使用:

public void showOverflowMenu(boolean showMenu){
    if(menu == null)
        return;
    menu.setGroupVisible(R.id.main_menu_group, showMenu);
}

我并不是说这是最好或唯一的方法,但对我来说效果很好。


2
我认为这是一个很棒的解决方案!它简单而干净。 - Zapnologica
我没有尝试过这个,但是 Silambarasan 给的下面的代码对我非常有效。 - Rizwan Sohaib
最佳解决方案!谢谢! - sorry bro
在我的情况下,使用“app:actionViewClass =”android.support.v7.widget.SearchView“与搜索项一起不起作用。当我关闭搜索视图时,出现了一些有趣的事情。 - Alberto M

23

为了在只需要的片段的操作栏(操作按钮)中显示操作项,请执行以下操作:

假设您希望“保存”按钮仅在接受项目输入的片段中显示,而不在查看项目列表的片段中显示,请将此内容添加到查看项目的片段的OnCreateOptionsMenu方法中:

public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    if (menu != null) {

        menu.findItem(R.id.action_save_item).setVisible(false);
    }
}

注意: 为了使此功能起作用,您需要在片段中的onCreate()方法(在我们的示例中是要隐藏项目按钮的项目视图片段)中添加setHasOptionsMenu(true),如下所示:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

可能不是最佳选择,但它有效且简单。


1
比被接受的答案更干净的解决方案 - Vibin

6

我想这肯定会有效...

// Declare
Menu menu;
MenuItem menuDoneItem;

// Then in your onCreateOptionMenu() method write the following...
@Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        this.menu=menu;
        inflater.inflate(R.menu.secutity, menu);
            }

// In your onOptionItemSelected() method write the following...
@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.done_item:
                this.menuDoneItem=item;
                someOperation();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

// Now Making invisible any menu item...
public void menuInvisible(){
setHasOptionsMenu(true);// Take part in populating the action bar menu
            menuDoneItem=(MenuItem)menu.findItem(R.id.done_item);
                menuRefresh.setVisible(false); // make true to make the menu item visible.
}

//Use the above method whenever you need to make your menu item visible or invisiable

你也可以参考这个链接来获取更多详细信息,它是非常有用的。


5
MenuItem Import = menu.findItem(R.id.Import);
  Import.setVisible(false)

4

试试这个

@Override
public boolean onCreateOptionsMenu(Menu menu){
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.custom_actionbar, menu);
    menu.setGroupVisible(...);
}

2
请添加一些注释,解释您所编写的代码如何回答问题 - 仅包含代码的答案是不鼓励的。 - Ajean

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
你好,我为您提供最佳解决方案。假设您需要在创建菜单方法中隐藏特定项目并在其他片段中显示该项目。我以两个菜单项为例,一个是编辑,另一个是删除。例如,以下是菜单xml代码:

sell_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">

<item
    android:id="@+id/action_edit"
    android:icon="@drawable/ic_edit_white_shadow_24dp"
    app:showAsAction="always"
    android:title="Edit" />

<item
    android:id="@+id/action_delete"
    android:icon="@drawable/ic_delete_white_shadow_24dp"
    app:showAsAction="always"
    android:title="Delete" />

现在在您的活动中覆盖这两个方法,并将一个字段变量 mMenu 设置为:
  private Menu mMenu;         //  field variable    


  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.sell_menu, menu);
    this.mMenu = menu;

    menu.findItem(R.id.action_delete).setVisible(false);
    return super.onCreateOptionsMenu(menu);
  }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.action_delete) {
       // do action
        return true;
    } else if (item.getItemId() == R.id.action_edit) {
      // do action
        return true;
    }

    return super.onOptionsItemSelected(item);
 }

在您的Activity中创建以下两个方法,并从片段中调用它们以隐藏和显示您的菜单项。这些方法如下:
```java public void hideMenuItem() { MenuItem item = findViewById(R.id.menu_item_id); item.setVisible(false); } public void showMenuItem() { MenuItem item = findViewById(R.id.menu_item_id); item.setVisible(true); } ```
请注意保留HTML标签,此处不提供解释。
public void showDeleteImageOption(boolean status) {
    if (menu != null) {
        menu.findItem(R.id.action_delete).setVisible(status);
    }
}

public void showEditImageOption(boolean status) {
    if (menu != null) {
        menu.findItem(R.id.action_edit).setVisible(status);
    }
}

这是我方面的解决方案,我认为这个解释会对您有所帮助。

1

好的,我花了几个小时来找到这个解决方案。显然,您可以从工具栏中获取菜单项并将其放置在活动或片段的任何位置。所以在我的情况下。

var menuItem = toolbar.menu;   

现在要从菜单项中获取特定项。
favIcon = menuItem.findItem(R.id.favourite);      

注意:favIcon是全局声明的MenuItem
现在,您可以为此图标执行任何操作
例如,使其不可见。
favIcon?.isVisible=false

1
你可以为每个片段创建一个菜单,以及一个全局变量来标记当前正在使用的片段。在onCreateOptionsMenu中检查变量的值,并填充正确的菜单。
 @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         if (fragment_it == 6) {
             MenuInflater inflater = getMenuInflater();
             inflater.inflate(R.menu.custom_actionbar, menu);
         }
     } 

但是在片段中如何编写onOptionSelected的代码? - Prachi
你应该在Activity的类中编写它,而不是在Fragment中。Fragment_it将指示您当前正在使用哪个片段,然后您可以填充相应的菜单。 - Ibraheem Saoud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接