441

我正在尝试从一组片段中将一个项目添加到选项菜单中。

我创建了一个新MenuFragment类,并为我希望在其中包含菜单项的片段扩展了它。这是代码:

爪哇:

public class MenuFragment extends Fragment {

    MenuItem fav;

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

    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        fav = menu.add("add");
        fav.setIcon(R.drawable.btn_star_big_off);
    }
}

科特林:

class MenuFragment : Fragment {

    lateinit var fav: MenuItem

    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        fav = menu.add("add");
        fav.setIcon(R.drawable.btn_star_big_off);
    }
}

由于某种原因,它onCreateOptionsMenu似乎没有运行。

4

21 回答 21

667

调用超级方法:

爪哇:

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

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // TODO Add your menu entries here
        super.onCreateOptionsMenu(menu, inflater);
    }

科特林:

    override fun void onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        // TODO Add your menu entries here
        super.onCreateOptionsMenu(menu, inflater)
    }

将日志语句放入代码中以查看是否未调用该方法或您的代码是否未修改菜单。

还要确保您正在调用setHasOptionsMenu(boolean)onCreate(Bundle)通知片段它应该参与选项菜单处理。

于 2011-11-29T10:29:38.177 回答
216

我遇到了同样的问题,但我认为最好总结并介绍最后一步以使其正常工作:

  1. 在 Fragment 的方法中添加 setHasOptionsMenu(true)onCreate(Bundle savedInstanceState)方法。

  2. 覆盖onCreateOptionsMenu(Menu menu, MenuInflater inflater)(如果您想在 Fragment 的菜单中做一些不同的事情)和 FragmentonOptionsItemSelected(MenuItem item)中的方法。

  3. onOptionsItemSelected(MenuItem item)Activity 的方法中,确保在onOptionsItemSelected(MenuItem item)Fragment 的方法中实现菜单项操作时返回 false。

一个例子:

活动

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.activity_menu_item:

            // Do Activity menu item stuff here
            return true;

        case R.id.fragment_menu_item:

            // Not implemented here
            return false;
        default:
            break;
    }

    return false;
}

分段

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

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // Do something that differs the Activity's menu here
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.activity_menu_item:

            // Not implemented here
            return false;
        case R.id.fragment_menu_item:

            // Do Fragment menu item stuff here
            return true;

        default:
            break;
    }

    return false;
}
于 2013-08-19T16:52:53.717 回答
161

如果您发现该onCreateOptionsMenu(Menu menu, MenuInflater inflater)方法没有被调用,请确保您从 Fragment 的onCreate(Bundle savedInstanceState)方法中调用以下内容:

setHasOptionsMenu(true)
于 2012-10-03T06:16:22.980 回答
79

如果您需要 amenu刷新webview特定内部的 a Fragment,您可以使用:

片段

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

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    // TODO Add your menu entries here
    inflater.inflate(R.menu.menu, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.exit:
        System.exit(1);
        break;

    case R.id.refresh:
        webView.reload();
        break;
    }
    return true;

}

菜单.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/exit" android:title="Exit" android:icon="@drawable/ic_action_cancel" />
    <item android:id="@+id/refresh" android:title="Refresh" android:icon="@drawable/ic_action_refresh" />
</menu>
于 2014-11-05T15:54:48.100 回答
46

TL;博士

使用android.support.v7.widget.Toolbar并执行以下操作:

toolbar.inflateMenu(R.menu.my_menu)
toolbar.setOnMenuItemClickListener {
    onOptionsItemSelected(it)
}

独立工具栏

大多数建议的解决方案setHasOptionsMenu(true)只有在父 Activity 的布局中有 Toolbar并通过setSupportActionBar(). 然后片段可以参与这个确切的ActionBar的菜单填充:

Fragment.onCreateOptionsMenu():初始化Fragment宿主的标准选项菜单的内容。

如果您想要一个特定片段的独立工具栏和菜单,您可以执行以下操作:

menu_custom_fragment.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_save"
        android:title="SAVE" />
</menu>

custom_fragment.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    ...

自定义片段.kt

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(layout.custom_fragment, container, false)
    val toolbar = view.findViewById<Toolbar>(R.id.toolbar)
    toolbar.inflateMenu(R.menu.menu_custom_fragment)
    toolbar.setOnMenuItemClickListener {
        onOptionsItemSelected(it)
    }
    return view
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.menu_save -> {
            // TODO: User clicked the save button
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

是的,就是这么简单。你甚至不需要覆盖onCreate()or onCreateOptionsMenu()

PS:这仅适用于android.support.v4.app.Fragmentand android.support.v7.widget.Toolbar(也一定要在你的 中使用AppCompatActivityand 一个AppCompat主题styles.xml)。

于 2018-06-22T15:11:19.557 回答
26

menu.xml您应该添加所有菜单项。然后,您可以隐藏在初始加载时不想看到的项目。

菜单.xml

<item
    android:id="@+id/action_newItem"
    android:icon="@drawable/action_newItem"
    android:showAsAction="never"
    android:visible="false"
    android:title="@string/action_newItem"/>

添加setHasOptionsMenu(true)onCreate() 方法以调用 Fragment 类中的菜单项。

片段类.java

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

您无需再次覆盖onCreateOptionsMenuFragment 类。onPrepareOptionsMenu可以通过片段中可用的覆盖方法更改(添加/删除)菜单项。

@Override
public void onPrepareOptionsMenu(Menu menu) {
    menu.findItem(R.id.action_newItem).setVisible(true);
    super.onPrepareOptionsMenu(menu);

}
于 2015-03-04T05:36:37.837 回答
20

就我而言,这是步骤。

第1步

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Here notify the fragment that it should participate in options menu handling.
    setHasOptionsMenu(true);
}

第2步

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // First clear current all the menu items
    menu.clear();

    // Add the new menu items
    inflater.inflate(R.menu.post_stuff, menu);

    super.onCreateOptionsMenu(menu, inflater);
}

第三步

 @Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.post_stuff:
            Log.d(TAG, "Will post the photo to server");
            return true;
        case R.id.cancel_post:
            Log.d(TAG, "Will cancel post the photo");
            return true;
        default:
            break;
    }
    return super.onOptionsItemSelected(item);
}
于 2018-02-06T23:47:34.103 回答
17

您需要在膨胀菜单之前使用 menu.clear() 。

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

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }
于 2015-03-26T13:36:13.093 回答
8

如果你想添加你的菜单自定义

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

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.menu_custom, menu);
}
于 2016-06-23T18:26:18.530 回答
7

我遇到了同样的问题,我的片段是 ViewPager 的页面。发生这种情况的原因是我在实例化 FragmentPagerAdapter 时使用了子片段管理器而不是活动支持片段管理器。

于 2013-07-26T15:04:52.420 回答
3

菜单文件:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/play"
        android:titleCondensed="Speak"
        android:showAsAction="always"
        android:title="Speak"
        android:icon="@drawable/ic_play">
    </item>
    <item
        android:id="@+id/pause"
        android:titleCondensed="Stop"
        android:title="Stop"
        android:showAsAction="always"
        android:icon="@drawable/ic_pause">
    </item>
</menu>

活动代码:

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.play:
            Toast.makeText(getApplicationContext(), "speaking....", Toast.LENGTH_LONG).show();
            return false;

        case R.id.pause:
            Toast.makeText(getApplicationContext(), "stopping....", Toast.LENGTH_LONG).show();
            return false;

        default:
            break;
    }

    return false;
}

片段代码:

@Override

public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.play:
            text = page.getText().toString();
            speakOut(text);

            // Do Activity menu item stuff here
            return true;

        case R.id.pause:
            speakOf();

            // Not implemented here
            return true;

        default:
            break;
    }
    return false;
}
于 2015-11-21T16:48:02.400 回答
3

你的代码很好。该方法中仅缺少 super :

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // TODO add your menu : 
    inflater.inflate(R.menu.my_menu, menu);
    //TODO call super
    super.onCreateOptionsMenu(menu, inflater);
}
于 2017-09-26T07:57:26.783 回答
2

我快疯了,因为这里的答案都不适合我。

要显示菜单,我必须调用: setSupportActionBar(toolbar)

完毕!

注意:如果您的toolbar视图不在同一个活动布局中,则不能直接从活动类中使用上面的调用,在这种情况下,您需要从片段类中获取该活动,然后调用setSupportActionBar(toolbar). 记住:您的活动类应该扩展 AppCompatActivity。

希望这个答案对您有所帮助。

于 2018-01-24T14:42:35.503 回答
2

setHasMenuOptions(true)如果应用程序有一个主题,或者 Activity 有它自己的工具栏,则 Set 有效ActionbarTheme.MaterialComponents.DayNight.DarkActionBar否则在onCreateOptionsMenu片段中不会被调用

如果您想使用独立的工具栏,您需要获取活动并将您的工具栏设置为支持操作栏

(requireActivity() as? MainActivity)?.setSupportActionBar(toolbar)

这让你的片段 onCreateOptionsMenu 被调用。

另一种选择是,您可以使用扩展工具栏自己的菜单toolbar.inflateMenu(R.menu.YOUR_MENU)和使用项目侦听器

toolbar.setOnMenuItemClickListener {
   // do something
   true
}
于 2020-09-10T18:08:07.897 回答
1

在创建片段视图后设置选项菜单对我来说效果很好。

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setHasOptionsMenu(true);        
}
于 2014-11-08T05:49:38.060 回答
1

我的问题略有不同。我做的一切都是正确的。但是我为托管片段的活动继承了错误的类。

所以要清楚,如果您onCreateOptionsMenu(Menu menu, MenuInflater inflater)在片段中覆盖,请确保承载此片段的活动类继承android.support.v7.app.ActionBarActivity(以防您希望支持低于 API 级别 11)。

我继承了android.support.v4.app.FragmentActivity支持低于 11 的 API 级别。

于 2015-04-19T19:23:04.863 回答
1

我要补充一件事,以及它对我不起作用的原因。

这类似于 Napster 的回答。

  1. 确保您的片段的托管活动扩展AppCompatActivity,而不是FragmentActivity

    public class MainActivity extends AppCompatActivity {
    
    }
    

    来自 FragmentActivity 的 Google 参考文档

    注意:如果你想实现一个包含操作栏的活动,你应该使用 ActionBarActivity 类,它是这个类的子类,因此允许你在 API 7 和更高级别使用 Fragment API。

  2. 要更新 Napster 的答案——ActionBarActivity现在已弃用,请AppCompatActivity改用。

  3. 使用时AppCompatActivity,还要确保将“活动主题设置为Theme.AppCompat或类似主题”(Google Doc)。

注意:android.support.v7.app.AppCompatActivity是该类的子android.support.v4.app.FragmentActivity类(请参阅AppCompatActivity参考文档)。

于 2015-10-22T23:54:19.923 回答
1

在您的菜单文件夹中创建一个 .menu xml 文件并添加此 xml

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

在您的片段类中覆盖此方法并

implement SearchView.OnQueryTextListener    in your fragment class



@Override
 public void onViewCreated(View view, Bundle savedInstanceState) {    
  super.onViewCreated(view, savedInstanceState);
  setHasOptionsMenu(true);

}

现在只需在片段类中设置您的菜单 xml 文件

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

    final MenuItem item = menu.findItem(R.id.action_search);
    final SearchView searchView = (SearchView)    
    MenuItemCompat.getActionView(item);


    MenuItemCompat.setOnActionExpandListener(item,
            new MenuItemCompat.OnActionExpandListener() {
                @Override
                public boolean onMenuItemActionCollapse(MenuItem item) {
                    // Do something when collapsed

                    return true; // Return true to collapse action view
                }

                @Override
                public boolean onMenuItemActionExpand(MenuItem item) {
                    // Do something when expanded
                    return true; // Return true to expand action view
                }
            });

}
于 2016-09-10T11:27:22.557 回答
0

如果以上所有方法都不起作用,您需要调试并确保函数 onCreateOptionsMenu 已被调用(通过放置调试或写入日志...)

如果它没有运行,可能你的 Android 主题不支持操作栏。 打开 AndroidManifest.xml 并设置android:theme主题支持操作栏的值:

 <activity
     android:name=".MainActivity"
     android:label="@string/app_name"
     android:theme="@style/Theme.AppCompat">
于 2016-05-23T06:47:27.783 回答
0

在你的onCreate方法上添加setHasOptionMenu()

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

然后覆盖你的onCreateOptionsMenu

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    menu.add("Menu item")
            .setIcon(android.R.drawable.ic_delete)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
于 2017-05-19T04:59:32.467 回答
0

这就是我在片段加载和销毁时分别隐藏和取消隐藏所有菜单选项所做的。它消除了指向nullfor的风险,R.id.your_menu_item并允许我在其他地方重用该片段。

lateinit var optionsMenu: Menu

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
    menu.iterator().forEach {
        it.isVisible = false
    }
    optionsMenu = menu
    super.onCreateOptionsMenu(menu, inflater)
}

override fun onDestroyView() {
    optionsMenu.iterator().forEach {
        it.isVisible = true
    }
    super.onDestroyView()
}
于 2021-07-22T18:53:21.873 回答