我有一个扩展Fragment
的片段类,并调用setHasOptionsMenu
参与菜单。此类还实现了onCreateOptionsMenu
,onPrepareOptionsMenu
和onOptionsItemSelected
。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
....
}
我在我的Activity(扩展FragmentTransaction
)中使用FragmentActivity
动态加载此片段。
但是没有调用任何菜单回调(onCreateOptionsMenu
,onPrepareOptionsMenu
和onOptionsItemSelected
)(我在这些方法中调试了一些断点)并且菜单未显示
我错过了什么吗?我需要在我的活动中添加一些内容吗?
我正在使用Android兼容性库,使用L11 SDK进行编译并在Xoom中进行测试。
编辑:我发现了问题。我的AndroidManifest目标是L11,这似乎隐藏了菜单按钮并阻止了回调被调用。但是,如果我从清单中删除它,我会丢失一些我需要的其他功能(例如列表中的激活状态)。有没有人知道如何解决这个问题(启用菜单按钮)而不从清单中删除targetSdkVersion=11
?
答案 0 :(得分:29)
Aromero, 不要忘记使用方法的片段版本覆盖onCreateOptionsMenu,类似于:
@Override
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.queue_options, menu);
super.onCreateOptionsMenu(menu, inflater);
}
顺便说一句,这会在片段中进行,并添加到Activity的膨胀菜单中(如果有的话)。我自己也有同样的问题,直到我想出来。
金
答案 1 :(得分:9)
如果你在ActionBarSherlock中遇到这个问题,你需要确保你的片段是SherlockFragments,而不仅仅是支持片段,而你要覆盖的是
public void onPrepareOptionsMenu (com.actionbarsherlock.view.Menu menu) {
不是
public void onPrepareOptionsMenu (android.view.Menu menu) {
如果你做了后者,你应该得到关于函数是final的警告,你无法覆盖它。这是一个警告,你试图覆盖错误的功能!
如果通过将类从SherlockFragment切换到仅仅片段来修复错误,则可以创建该函数。 。 。但它不会被调用。
答案 2 :(得分:9)
我遇到了同样的问题,但我认为最好总结一下并介绍最后一步让它发挥作用:
在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) {
// 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;
}
我希望这会有所帮助。
干杯。
答案 3 :(得分:6)
如果你有一个活动和一个片段,每个片段都加载菜单项,那么你需要特别注意你使用的覆盖。
活动可以覆盖 onOptionsItemSelected 和 onMenuItemSelected ,但片段只能覆盖 onOptionsItemSelected 。
如果您在活动中覆盖 onMenuItemSelected 并在片段中覆盖 onOptionsItemSelected ,则您的片段覆盖将永远不会被触发。
相反,在activity和fragment中使用 onOptionsItemSelected 。
答案 4 :(得分:5)
您需要确保在片段中调用setHasOptionsMenu(true);
onCreate
或onCreateView
。
您还需要在片段中实现onCreateOptionsMenu
的覆盖。
答案 5 :(得分:4)
另一种可能的情况是,在每个片段中使用公共ID进行公共操作时;例如R.id.action_add
今天我遇到了这种情况:点击选项菜单[add]被调用“错误”onOptionItemSelected
因为每个片段(使用DrawerLayout
动态替换)具有相同的R.id.action_add
。
简短的故事,如果您有这种情况,请始终检查您的片段是否可见:
if (!isVisible()) return false;
长篇故事,注意onOptionItemSelected
链!
MainActivity
|
| onOptionItemSelected
+-----------------------
| return false
|
MyCoolFragment1
|
| onOptionItemSelected
+-----------------------
| return false
|
MyCoolFragment2
|
| onOptionItemSelected
+-----------------------
| return true
|
[item selection handled]
如果您添加片段(类似):
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content_frame, MyCoolFragment1.newInstance())
.commit()
你已经在每个片段中为一个共同的动作(让我们说R.id.action_add)定义了相同的id; 不要忘记将这一行添加到每个:if(!isVisible())返回false;
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!isVisible()) return false; // <-- Not visible? skip!
if (item.getItemId() == R.id.action_add) {
//.TODO whatever
return true; //.Handled!
}
return false; //.Skip
}
答案 6 :(得分:3)
当我将ViewPagerIndicator与ActionBarSherlock结合使用时,我遇到了这个问题。虽然看起来这是fixed我仍然遇到了问题。我找到的工作是手动调用片段。
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
Toast.makeText(this, "From activity", Toast.LENGTH_SHORT).show(); // TODO
Fragment currentFragment = mAdapter.getItem(mPager.getCurrentItem());
if (currentFragment != null && currentFragment instanceof SherlockFragment)
{
((SherlockFragment)currentFragment).onOptionsItemSelected(item);
}
return super.onOptionsItemSelected(item);
}
答案 7 :(得分:2)
我发现了问题。 AndroidManifest的目标是SDK 11,这似乎隐藏了菜单按钮并阻止调用回调。我认为这打破了菜单按钮的兼容性,似乎被Android 3.0中的操作栏取代了
答案 8 :(得分:1)
我认为您已在onCreateOptionsMenu
的班级中实施了onPrepareOptionsMenu
,onOptionsItemSelected
和extends Fragment
。尝试在您正在加载此片段的Activity类中执行此操作
答案 9 :(得分:1)
我有同样的问题和解决方案对我有用:
删除或评论任何onOptionsItemSelected(),onMenuItemSelected()甚至onPrepareOptionMenu()并仅留在Activity onCreateOptionsMenu()中:
@Override
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater=getMenuInflater();
inflater.inflate(R.layout.menu, menu);
return true;
}
在Fragment类中,在onCreateView()中,输入:
setHasOptionsMenu(true);
在Fragment类中添加:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu,inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case R.id.action_insert:
//doing stuff
return true;
}
return false;
}
在Android 4.4上测试并使用
答案 10 :(得分:1)
来自Android开发者网站 - link
注意:如果您通过片段从片段中膨胀菜单项 class onCreateOptionsMenu()回调,系统调用 当用户选择其中一个时,该片段的onOptionsItemSelected() 那些物品。但是,活动有机会处理该事件 首先,所以 系统首先调用onOptionsItemSelected() 活动,在调用片段的相同回调 之前。确保 活动中的任何片段也有机会处理 回调,始终将调用传递给超类作为默认值 当您不处理该项目时,行为而不是返回 false 。
因此Marco HC是最好的答案。
答案 11 :(得分:1)
如果您的工具栏是在父活动xml中定义的,请确保在片段中执行此操作
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
....
Toolbar toolbar = (Toolbar)getActivity().findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
setHasOptionsMenu(true);
}
当然,覆盖onCreateOptionsMenu,如下所示
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.edit_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
这是唯一对我有用的解决方案!