我正在尝试从一组片段中将选项添加到选项菜单中。
我创建了一个新的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);
}
}
出于某种原因,onCreateOptionsMenu
似乎无法运行。
答案 0 :(得分:564)
调用超级方法:
@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);
}
在代码中放置日志语句,以查看是否未调用该方法,或者代码是否未修改该菜单。
同时确保您在SetHasOptionsMenu
中调用onCreate
来通知片段它应该参与选项菜单处理。
答案 1 :(得分:185)
我遇到了同样的问题,但我认为最好总结一下并介绍最后一步让它运转起来:
在Fragment的onCreate(Bundle savedInstanceState)
方法中添加setHasOptionsMenu(true)方法。
在片段中覆盖onCreateOptionsMenu(Menu menu, MenuInflater inflater)
(如果您想在片段菜单中执行不同的操作)和onOptionsItemSelected(MenuItem item)
方法。
在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;
}
答案 2 :(得分:152)
如果您发现未调用onCreateOptionsMenu(Menu menu, MenuInflater inflater)
方法,请务必从Fragment的onCreate(Bundle savedInstanceState)
方法中调用以下内容:
setHasOptionsMenu(true)
答案 3 :(得分:50)
如果您需要menu
来刷新特定webview
内的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;
}
<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>
答案 4 :(得分:23)
在menu.xml
中,您应该添加所有菜单项。然后,您可以隐藏在初始加载中不想看到的项目。
<强> menu.xml文件强>
<item
android:id="@+id/action_newItem"
android:icon="@drawable/action_newItem"
android:showAsAction="never"
android:visible="false"
android:title="@string/action_newItem"/>
在onCreate()方法中添加setHasOptionsMenu(true)
以调用Fragment类中的菜单项。
<强> FragmentClass.java 强>
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
您无需再次覆盖Fragment类中的onCreateOptionsMenu
。可以通过覆盖Fragment中可用的onPrepareOptionsMenu
方法来更改(添加/删除)菜单项。
@Override
public void onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.action_newItem).setVisible(true);
super.onPrepareOptionsMenu(menu);
}
答案 5 :(得分:16)
在充气菜单之前,您需要使用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);
}
答案 6 :(得分:11)
使用android.support.v7.widget.Toolbar
并执行以下操作:
toolbar.inflateMenu(R.menu.my_menu)
toolbar.setOnMenuItemClickListener {
onOptionsItemSelected(it)
}
大多数建议的解决方案,例如setHasOptionsMenu(true)
仅在父活动的布局中具有工具栏并通过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" />
...
CustomFragment.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()
或onCreateOptionsMenu()
。
PS:这仅适用于android.support.v4.app.Fragment
和android.support.v7.widget.Toolbar
(还请确保在AppCompatActivity
中使用AppCompat
和styles.xml
主题)。 / p>
答案 7 :(得分:9)
就我而言,这是步骤。
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Here notify the fragment that it should participate in options menu handling.
setHasOptionsMenu(true);
}
@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);
}
答案 8 :(得分:7)
我遇到了同样的问题,我的片段是ViewPager的页面。它发生的原因是我在实例化FragmentPagerAdapter时使用子片段管理器而不是活动支持片段管理器。
答案 9 :(得分:7)
如果您想添加菜单自定义
@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);
}
答案 10 :(得分: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;
}
答案 11 :(得分:3)
你的代码很好。方法中只缺少超级:
@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);
}
答案 12 :(得分:2)
我变得疯狂,因为这里没有任何答案对我有用。
要显示我必须致电的菜单: setSupportActionBar(toolbar)
完成!
注意:如果您的toolbar
视图不在同一活动布局中,则无法直接在活动类中使用上述调用,在这种情况下,您需要从片段类中获取该活动然后调用setSupportActionBar(toolbar)
。记住:您的活动类应扩展AppCompatActivity。
希望这个答案可以帮助你。
答案 13 :(得分:1)
在菜单文件夹中创建一个.menu xml文件并添加此xml
/**
* Array adapter for main vendor listview
*/
private class VendorMainListAdapter extends ArrayAdapter<String> {
ArrayList<String> VendorNameArrayList = new ArrayList<String>();
private Activity activity;
public VendorMainListAdapter(Activity a, int resource, ArrayList<String> VendorNameArrayList) {
super(a, resource, VendorNameArrayList);
activity = a;
this.VendorNameArrayList = VendorNameArrayList;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View row = inflater.inflate(R.layout.activity_vendor_list_item, parent, false);
final TextView tvVendorName=(TextView)row.findViewById(R.id.tvVendorNames);
final GridView gvCakeList=(GridView) row.findViewById(R.id.gvCakeList);
tvVendorName.setText(VendorNameArrayList.get(position));
int size=CakeNameArrayList.size();
// Calculated single Item Layout Width for each grid element ....
int width = 150 ;
DisplayMetrics dm = new DisplayMetrics();
HomeScreen.this.getWindowManager().getDefaultDisplay().getMetrics(dm);
float density = dm.density;
int totalWidth = (int) (width * size * density);
singleItemWidth = (int) (width * density);
int height= 100;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
totalWidth, singleItemWidth);
gvCakeList.setLayoutParams(params);
gvCakeList.setColumnWidth(singleItemWidth);
gvCakeList.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
gvCakeList.setNumColumns(size);
gvCakeList.setHorizontalSpacing(10);
//Here I have set the adapter for the gridview
gvCakeList.setAdapter(new CakeListGridViewAdapter(HomeScreen.this,CakeIdArrayList,CakeNameArrayList,
CakePriceArrayList,CakePicArrayList));
gvCakeList.setSelection(mSelected);
//this is the onitemclicklistener for this gridview
gvCakeList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.e("item clicked ", String.valueOf(i));
}
});
row.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("oops","you clicked parent");
}
});
return row;
}
}
在你的片段类中覆盖此方法和
<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" />
现在只需在片段类
中设置菜单xml文件implement SearchView.OnQueryTextListener in your fragment class
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
}
答案 14 :(得分:1)
我要补充一点,以及它不适合我的原因。
这与Napster的答案相似。
确保您的片段的托管活动延伸AppCompatActivity
,而不是FragmentActivity
!
public class MainActivity extends AppCompatActivity {
}
从FragmentActivity的Google参考Documentation:
注意:如果要实现包含操作栏的活动,则应该使用ActionBarActivity类,它是此类的子类,因此允许您在API级别7及更高级别上使用Fragment API。
要更新Napster的回答 - ActionBarActivity
现已弃用,请改用AppCompatActivity
。
使用AppCompatActivity
时,还要确保将活动主题设置为Theme.AppCompat
或类似主题&#34; (Google Doc)。
注意:android.support.v7.app.AppCompatActivity
是android.support.v4.app.FragmentActivity
类的子类(请参阅AppCompatActivity参考文档)。
答案 15 :(得分:1)
我的问题略有不同。我做的一切都很对。但是我继承了托管该片段的活动的错误类。
所以要明确的是,如果要覆盖片段中的onCreateOptionsMenu(Menu menu, MenuInflater inflater)
,请确保托管此片段的活动类继承android.support.v7.app.ActionBarActivity
(如果您希望支持以下API级别11)。
我继承了android.support.v4.app.FragmentActivity
以支持低于11的API级别。
答案 16 :(得分:1)
创建片段视图后设置选项菜单对我来说效果很好。
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
答案 17 :(得分:0)
如果以上所有方法都不起作用,则需要调试并确保已调用函数onCreateOptionsMenu(通过放置调试或写日志...)
如果没有运行,可能您的Android主题不支持操作栏。
打开AndroidManifest.xml并使用主题支持操作栏设置android:theme
的值:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat">
答案 18 :(得分:0)
添加 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);
}
答案 19 :(得分:0)
setHasMenuOptions(true)
,例如Actionbar
,则 Set Theme.MaterialComponents.DayNight.DarkActionBar
是有效的,或者Activity具有它自己的工具栏,否则片段中的onCreateOptionsMenu
不会被调用。
如果您想使用独立的工具栏,则需要激活并通过以下方式将工具栏设置为支持操作栏:
(requireActivity() as? MainActivity)?.setSupportActionBar(toolbar)
这将使您的片段onCreateOptionsMenu被调用。
另一种选择是,您可以使用toolbar.inflateMenu(R.menu.YOUR_MENU)
扩展工具栏自身的菜单,并使用
toolbar.setOnMenuItemClickListener {
// do something
true
}
答案 20 :(得分:0)
这是我分别在加载和销毁片段时隐藏和取消隐藏所有菜单选项的操作。它消除了将 null
指向 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()
}