Android工具栏:为不同片段添加菜单项

105

我有一个工具栏和一个导航抽屉。当我启动我的应用程序时,会创建工具栏和导航抽屉。当我在导航抽屉中点击项目时,它会启动新的片段并保留相同的工具栏。我如何将菜单项添加到工具栏中,例如搜索、添加、编辑,当我启动特定的片段时?我不希望它们在程序开始时就出现,而是在运行时动态创建。另外,我该如何单击这些按钮并启动其他片段?我希望在一个片段中,工具栏中的编辑按钮与另一个片段中的编辑按钮执行不同的操作。谢谢!

Menu_toolbar:

<?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/edit"
    android:orderInCategory="1"
    android:title="Edit"
    app:showAsAction="always"
    android:icon="@drawable/pencil_icon"/>
<item android:id="@+id/add"
    android:orderInCategory="1"
    android:title="Add"
    app:showAsAction="always"
    android:icon="@drawable/plus_icon"/>

工具栏:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="55dp"
android:background="#10a1ff"
android:title="Home"
/>
12个回答

188

将类似的代码添加到您的片段中:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
    View v = inflater.inflate(R.layout.library_fragment, parent, false);
    setHasOptionsMenu(true);
    return v;
}


@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
   inflater.inflate(R.menu.your_menu_xml, menu);
   super.onCreateOptionsMenu(menu, inflater);
}

通过这种方式,您可以定制片段的菜单。


20
这是正确的答案,因为在片段中调用setHasOptionsMenu(true)方法是调用onCreateOptionsMenu方法所必需的。 - John Slavick
21
onCreateOptionsMenu 中记得调用 menu.clear() - 否则你也会继承父级的菜单。 - Dart Dega
@DartDega,我应该把清除代码放在哪里?片段还是活动中,先生?我在我的片段中没有看到菜单项。 - famfamfam
这个能在API 28级上运行吗?我仍然看到主活动菜单项。 - ArdenDev

37

最好的方法是:

1. 在 Activity 中找到工具栏并将其设置为 supportActionBar。

Toolbar actionBarToolBar = (Toolbar) findViewById(R.id.my_toobar);
setSupportActionBar(actionBarToolBar);

2. 接下来,为同一个Activity中的不同片段处理选项菜单将变得易如反掌。

在每个片段中按照您的需求执行以下操作:

在OnCreateView方法中调用:

setHasOptionsMenu(true);

最后,

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.main, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

为了管理菜单项的点击,我们有onOptionsItemSelected:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_search :
            Log.i("item id ", item.getItemId() + "");
        default:
            return super.onOptionsItemSelected(item);
    }
}

1
setHasOptionsMenu(true)非常有用!谢谢。 - J.Dragon

36

以下是如何动态创建菜单的方法:http://www.101apps.co.za/index.php/articles/using-toolbars-in-your-apps.html

已编辑:

Toolbar actionBarToolBar = (Toolbar) findViewById(R.id.my_toobar);
setSupportActionBar(actionBarToolBar);
actionBarToolBar.setNavigationIcon(R.drawable.icon);
actionBarToolBar.setNavigationContextDescription(getResources().getString(R.string.desc);
actionBarToolBar.setLogo(R.drawable.other_icon);
actionBarToolBar.setLogoDescription(getResources().getString(R.string.other_desc);
actionBarToolBar.inflateMenu(R.menu.fragment_menu);

4
使用actionBarToolbar.setOnMenuItemClickListener()来处理菜单项的操作。在这种情况下,onOptionsItemSelected()不会被调用。 - Lahiru Chandima
5
抱歉,给定的链接已经不存在。 - Ashvin solanki

28

最简单的选择是执行

toolbar.inflateMenu(R.menu.fragment_menu);

并处理菜单项的点击

toolbar.setOnMenuItemClickListener {
    when (it.itemId) {
        R.id.nav_example -> doThat()
    }
    true
}

菜单的clickListener可以像这样膨胀:https://dev59.com/K18d5IYBdhLWcg3wt0Ky#26512114 - Rafael

11

在每个片段中覆盖 onCreateOptionsMenu 方法。

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.your_menu_xml, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@JoeEigi 为什么你想要不同的工具栏?你可以设置不同的标题和菜单。 - Ellie Zou
@JoeEigi 是的,您可以通过填充自定义菜单 xml 来创建自定义菜单。调用 setTitle() 可以添加标题。 - Ellie Zou
@JoeEigi 看起来你的上下文有误,请查看此链接:https://dev59.com/IF8d5IYBdhLWcg3wTAl- - Allen Chan
1
我在清单文件中关闭了ActionBar,但它仍然显示在我的活动布局中,位于工具栏之上。我该如何去掉它? - Joe Eigi
是的,我已经这样做了,但它仍然出现在我的布局中,只是移出了视图。 - Joe Eigi
@JoeEigi 这很奇怪。你写的是 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);setSupportActionBar(toolbar); 吗? - Ellie Zou

7
我正确解决了这个问题。我的解决方案如下所示代码:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    mRootView = inflater.inflate(R.layout.fragment_order_history, container, false);
    //getActivity().invalidateOptionsMenu();


    setHasOptionsMenu(true);

    return mRootView;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.main, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

是的,我已经成功地显示了菜单。但是如何在片段关闭时隐藏此菜单,我的意思是当我们从一个片段切换到另一个片段时,例如从a->b,a的菜单仍然可见于片段b的工具栏中。 - Zeeshan Ahmed
在片段b的onCreateView方法中使用setHasOptionsMenu(false)。 - Kannan_SJD

6

我曾经遇到过同样的问题,我想根据显示的片段相应地替换工具栏菜单。

我现在面临的问题是菜单添加到了上一个菜单中。

为了仅显示片段的菜单,我建议:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
     menu.clear(); //Empty the old menu
     inflater.inflate(R.menu.menu_fragment1, menu);
     super.onCreateOptionsMenu(menu, inflater);
}

希望这会有所帮助。


2
在调用.clear()之前,只需检查menu!= null即可。 - mapo

3
使用新的MaterialToolbar非常容易创建溢出菜单并使用它:
<com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/toolbar"
        android:layout_width="0dp"
        android:layout_height="?attr/actionBarSize"
        app:navigationIcon="@drawable/ic_menu"
        app:menu="@menu/main_menu"/>

然后在代码中设置OnClick监听器,只需添加以下内容:

toolbar.setOnMenuItemClickListener {
            // .. DO SOMETHING HERE
            false
        }

3
以下是显示不同菜单选项并使用不同片段的步骤:
步骤1:调用setHasOptionsMenu(true)。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        setHasOptionsMenu(true)
        super.onViewCreated(view, savedInstanceState)

    }

步骤二:展开与您的片段相关的选项菜单项。
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
    // To clear previously added menu items
    menu?.clear()
    inflater?.inflate(R.menu.your_fragment_menu, menu)
    super.onCreateOptionsMenu(menu, inflater)
}

这帮助我删除了出现在我的新菜单上的不需要的菜单按钮。 - Im Batman

1

Inside XML add this line

app:menu="@menu/main_menu"

1
其实你是对的! 你可以通过xml指定它,然后在片段中:override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) toolBar.setNavigationOnClickListener { activity?.onBackPressed() } searchView = toolBar.menu.findItem(R.id.action_search).actionView as SearchView searchView.setOnQueryTextListener(this) } - user3193413

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