我正在尝试从一组片段中将一个项目添加到选项菜单中。
我创建了一个新的 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
似乎没有运行。
调用超级方法:
爪哇:
@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)
}
将日志语句放入代码中以查看是否未调用该方法或您的代码是否未修改菜单。
还要确保您在 onCreate(Bundle)
中调用 setHasOptionsMenu(boolean)
以通知片段它应该参与选项菜单处理。
我遇到了同样的问题,但我认为最好总结并介绍最后一步以使其正常工作:
在 Fragment 的 onCreate(Bundle savedInstanceState) 方法中添加 setHasOptionsMenu(true) 方法。在 Fragment 中覆盖 onCreateOptionsMenu(Menu menu, MenuInflater inflater) (如果你想在 Fragment 的菜单中做一些不同的事情)和 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;
}
setHasOptionsMenu(true);
谢谢
如果您发现 onCreateOptionsMenu(Menu menu, MenuInflater inflater)
方法没有被调用,请确保从 Fragment 的 onCreate(Bundle savedInstanceState)
方法调用以下内容:
setHasOptionsMenu(true)
Toolbar
并且必须在 onCreateView()
中调用 setHasOptionsMenu(true)
而不是 onCreate()
才能完成它。
如果您需要 menu
来刷新特定 Fragment
内的 webview
,您可以使用:
分段:
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>
TL;博士
使用 android.support.v7.widget.Toolbar
并执行以下操作:
toolbar.inflateMenu(R.menu.my_menu)
toolbar.setOnMenuItemClickListener {
onOptionsItemSelected(it)
}
独立工具栏
大多数建议的解决方案(如 setHasOptionsMenu(true)
)仅在 父 Activity 的布局中有工具栏并通过 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()
或 onCreateOptionsMenu()
。
PS:这仅适用于 android.support.v4.app.Fragment
和 android.support.v7.widget.Toolbar
(也请务必在 styles.xml
中使用 AppCompatActivity
和 AppCompat
主题)。
onPrepareOptionsMenu
的替代方法?
在 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"/>
在 onCreate() 方法中添加 setHasOptionsMenu(true)
以调用 Fragment 类中的菜单项。
片段类.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);
}
就我而言,这是步骤。
步骤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);
}
menu.clear()
清除了上一个菜单。为我工作:)
您需要在膨胀菜单之前使用 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);
}
如果你想添加你的菜单自定义
@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);
}
我遇到了同样的问题,我的片段是 ViewPager 的页面。发生这种情况的原因是我在实例化 FragmentPagerAdapter 时使用了子片段管理器而不是活动支持片段管理器。
菜单文件:
<?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;
}
你的代码很好。该方法中仅缺少 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);
}
我快疯了,因为这里的答案都不适合我。
要显示我必须调用的菜单: setSupportActionBar(toolbar)
完毕!
注意:如果您的 toolbar
视图不在同一个活动布局中,则不能直接从活动类中使用上述调用,在这种情况下,您需要从片段类中获取该活动,然后调用 { 2}。记住:您的活动类应该扩展 AppCompatActivity。
希望这个答案对您有所帮助。
如果应用程序具有带有 Actionbar
的主题(例如 Theme.MaterialComponents.DayNight.DarkActionBar
)或 Activity 具有自己的工具栏,则设置 setHasMenuOptions(true)
有效,否则片段中的 onCreateOptionsMenu
不会被调用。
如果您想使用独立的工具栏,您需要获取活动并将您的工具栏设置为支持操作栏
(requireActivity() as? MainActivity)?.setSupportActionBar(toolbar)
这让你的片段 onCreateOptionsMenu 被调用。
另一种选择是,您可以使用 toolbar.inflateMenu(R.menu.YOUR_MENU)
扩展工具栏自己的菜单,并使用
toolbar.setOnMenuItemClickListener {
// do something
true
}
在创建片段视图后设置选项菜单对我来说效果很好。
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
我的问题略有不同。我做的一切都是正确的。但是我为托管片段的活动继承了错误的类。
所以要明确一点,如果您在片段中覆盖 onCreateOptionsMenu(Menu menu, MenuInflater inflater)
,请确保承载此片段的活动类继承 android.support.v7.app.ActionBarActivity
(以防您希望支持低于 API 级别 11)。
我继承了 android.support.v4.app.FragmentActivity
以支持低于 11 的 API 级别。
我要补充一件事,以及它对我不起作用的原因。
这类似于 Napster 的回答。
确保 Fragment 的托管活动扩展 AppCompatActivity,而不是 FragmentActivity! public class MainActivity extends AppCompatActivity { } 来自 FragmentActivity 的 Google 参考文档:注意:如果你想实现一个包含操作栏的活动,你应该使用 ActionBarActivity 类,它是这个类的子类,因此允许你在 API 级别 7 及更高级别上使用 Fragment API。要更新 Napster 的答案——ActionBarActivity 现在已被弃用,请改用 AppCompatActivity。使用 AppCompatActivity 时,还要确保将“活动主题设置为Theme.AppCompat 或类似主题”(Google Doc)。
注意:android.support.v7.app.AppCompatActivity
是 android.support.v4.app.FragmentActivity
类的子类(请参阅 AppCompatActivity 参考文档)。
在您的菜单文件夹中创建一个 .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
}
});
}
如果以上所有方法都不起作用,您需要调试并确保函数 onCreateOptionsMenu 已被调用(通过放置调试或写入日志...)
如果它没有运行,可能你的 Android 主题不支持操作栏。 打开 AndroidManifest.xml 并使用主题支持操作栏设置 android:theme
的值:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat">
在你的 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);
}
这就是我在片段加载和销毁时分别隐藏和取消隐藏所有菜单选项所做的。它消除了为 R.id.your_menu_item
指向 null
的风险,并允许我在其他地方重用该片段。
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()
}
如果以上选项都不适合您,请在您的片段中尝试以下操作:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
....
toolBar = rootView.findViewById(R.id.import_contacts_toolbar)
toolBar?.title = "Your title"
toolBar?.subtitle = "yor subtitile"
contactsActivity().setSupportActionBar(toolBar)
toolBar?.inflateMenu(R.menu.import_contacts_menu)
...
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.1 -> {
return true
}
R.id.2 -> {
return true
}
}
return false
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
menu.clear()
inflater.inflate(R.menu.import_contacts_menu, menu)
super.onCreateOptionsMenu(menu, inflater)
val search = menu.findItem(R.id.action_search)
val searchView = search.actionView as SearchView
searchView.requestFocus()
val txtSearch = searchView.findViewById<View>(androidx.appcompat.R.id.search_src_text) as EditText
txtSearch.hint = "Search..."
txtSearch.setHintTextColor(Color.WHITE);
txtSearch.setTextColor(Color.WHITE)
try {
val f: Field = TextView::class.java.getDeclaredField("mCursorDrawableRes")
f.setAccessible(true)
f.set(txtSearch, R.drawable.search_edit_text_cursor)
} catch (ignored: Exception) {
Log.d(TAG, "failed to expose cursor drawable $ignored")
}
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
return false
}
override fun onQueryTextChange(newText: String): Boolean {
return true
}
})
searchView.setOnCloseListener {
}
}
就我而言,我有一个设置为始终可见的搜索菜单项。这是它的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_search"
app:showAsAction="always"
app:actionViewClass="androidx.appcompat.widget.SearchView"
android:title="Search"/>
<item android:id="@+id/1"
android:title="1">
</item>
<item android:id="@+id/2"
android:title="2">
</item>
</menu>
自 androidx.activity:activity:1.4.0
以来,有一种新方法可以做到这一点
您应该使用 MenuProvider API。
它的用法如下:
您应该在 onViewCreated
中调用 addMenuProvider
,而不是调用 super.setHasOptionMenu
并实现 onCreateOptionsMenu
。
一个例子:
class ExampleFragment : Fragment(R.layout.fragment_example) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// The usage of an interface lets you inject your own implementation
val menuHost: MenuHost = requireActivity()
// Add menu items without using the Fragment Menu APIs
// Note how we can tie the MenuProvider to the viewLifecycleOwner
// and an optional Lifecycle.State (here, RESUMED) to indicate when
// the menu should be visible
menuHost.addMenuProvider(object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
// Add menu items here
menuInflater.inflate(R.menu.example_menu, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
// Handle the menu selection
return true
}
}, viewLifecycleOwner, Lifecycle.State.RESUMED)
}
不定期副业成功案例分享