40

我有一个片段类,它扩展Fragment并调用setHasOptionsMenu参与菜单。该类还实现onCreateOptionsMenu,onPrepareOptionsMenuonOptionsItemSelected.

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

FragmentTransaction在我的 Activity (扩展FragmentActivity)中使用 a 动态加载这个片段。

但是,没有调用任何菜单回调(onCreateOptionsMenuonPrepareOptionsMenuonOptionsItemSelected(我已经在这些方法中使用一些断点进行了调试),并且没有显示菜单。

我错过了什么吗?我需要在我的活动中添加一些东西吗?

我正在使用 Android 兼容性库,使用 L11 SDK 进行编译并在 Xoom 中进行测试。

编辑:我发现了问题。我的 AndroidManifest 的目标是 L11,这似乎隐藏了菜单按钮并防止调用回调。但是,如果我从清单中删除它,我会失去一些我需要的其他功能(例如列表中的激活状态)。有谁知道如何解决这个问题(启用菜单按钮)而不targetSdkVersion=11从清单中删除?

4

12 回答 12

29

Aromero,不要忘记使用片段版本的方法覆盖onCreateOptionsMenu,类似这样:

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

顺便说一句,这会进入片段,并添加到 Activity 的膨胀菜单(如果有的话)。我自己也有同样的问题,直到我弄清楚了。

于 2011-06-08T15:57:50.740 回答
9

如果您在使用 ActionBarSherlock 时遇到此问题,则需要确保您的 Fragments 是 SherlockFragments,而不仅仅是 SupportFragments,并且您要覆盖的是

public void onPrepareOptionsMenu (com.actionbarsherlock.view.Menu menu) {

不是

public void onPrepareOptionsMenu (android.view.Menu menu) {

如果你做后者,你应该得到某种关于函数是最终的并且你无法覆盖它的警告。这是一个警告,您正在尝试覆盖错误的功能!

如果通过将类从 SherlockFragment 切换为纯 Fragment 来修复错误,则可以创建函数。. . 但它不会被调用。

于 2013-01-24T21:56:12.960 回答
9

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

  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) {
    // 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-19T17:04:31.427 回答
6

如果您有一个活动和一个片段,每个都加载菜单项,那么您需要特别注意您使用哪些覆盖。

活动可以覆盖onOptionsItemSelectedonMenuItemSelected,但是片段只能覆盖onOptionsItemSelected

如果您在活动中覆盖onMenuItemSelected并在片段中覆盖onOptionsItemSelected,则您的片段覆盖将永远不会被触发。

相反,在活动和片段中使用onOptionsItemSelected 。

于 2012-09-11T00:07:03.973 回答
5

您需要确保您在片段中调用setHasOptionsMenu(true); onCreate或被onCreateView调用。

您还需要onCreateOptionsMenu在片段内部实现覆盖。

于 2012-11-05T22:40:53.553 回答
4

另一种可能的情况是,当您在每个片段中使用一个公共 id 来执行一个公共操作时;例如 R.id.action_add

今天我遇到了这样的情况:点击选项菜单 [add] 被调用“错误” onOptionItemSelected,因为每个片段(使用 a 动态替换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()) return 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
}
于 2014-02-04T10:15:42.423 回答
3

当我将 ViewPagerIndicator 与 ActionBarSherlock 结合使用时,我遇到了这个问题。虽然看起来这是固定的,但我仍然遇到了问题。我发现的解决方法是手动调用片段。

@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);

}
于 2012-07-11T23:58:06.790 回答
2

我发现了问题。AndroidManifest 的目标是 SDK 11,这似乎隐藏了菜单按钮并防止调用回调。我认为这破坏了似乎被 Android 3.0 中的操作栏取代的菜单按钮的兼容性

于 2011-06-12T19:57:06.527 回答
1

我想你已经实现了onCreateOptionsMenuonPrepareOptionsMenu并且onOptionsItemSelected在课堂上说extends Fragment。尝试在加载此片段的 Activity 类中执行此操作

于 2011-06-08T13:56:27.213 回答
1

我有同样的问题和对我有用的解决方案是:

  1. 删除或评论任何 onOptionsItemSelected() ,onM​​enuItemSelected() 甚至 onPrepareOptionMenu() 并仅留在活动 onCreateOptionsMenu() 中:

    @Override
    public boolean onCreateOptionsMenu(Menu menu){
    MenuInflater inflater=getMenuInflater();
    inflater.inflate(R.layout.menu, menu);
    return true;
    }
    
  2. 在 Fragment 类的 onCreateView() 中,输入:

    setHasOptionsMenu(true);
    
  3. 在片段类中添加:

    @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 上测试并运行

于 2014-04-15T18:20:47.480 回答
1

来自 android 开发者网站 -链接

注意:如果您通过 Fragment 类的 onCreateOptionsMenu() 回调从片段中膨胀菜单项,则系统会在用户选择其中一项时为该片段调用 onOptionsItemSelected()。但是,活动有机会首先处理事件,因此系统首先在活动上调用 onOptionsItemSelected(),然后再为片段调用相同的回调。为确保活动中的任何片段也有机会处理回调,请始终将调用作为默认行为传递给超类,而不是在不处理项目时返回false 。

因此, Marco HC是最好的答案。

于 2014-10-30T07:36:14.157 回答
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);
}

这是唯一对我有用的解决方案!

于 2017-08-29T07:57:32.627 回答