【问题标题】:(Deprecated) Fragment onOptionsItemSelected not being called(已弃用)片段 onOptionsItemSelected 未被调用
【发布时间】:2019-05-29 22:49:36
【问题描述】:

编辑: 这个问题是针对已弃用的夏洛克动作栏的。现在应该改用 Android 支持库

我为我的fragment 添加了一个名为 share 的操作栏菜单选项,该选项出现但未捕获选择事件

我是这样添加的

@Override
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {
    MenuItem item = menu.add(0, 7,0, R.string.share);
    item.setIcon(R.drawable.social_share).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}

尝试在fragmentfragment activity 之类中捕获它

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case 7:
            Intent share = new Intent(Intent.ACTION_SEND);
            share.setType("text/plain");
            share.putExtra(Intent.EXTRA_TEXT, "I'm being sent!!");
            startActivity(Intent.createChooser(share, "Share Text"));
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

我在onCreate() 中有setHasOptionsMenu(true);

【问题讨论】:

    标签: android android-fragments android-actionbar


    【解决方案1】:

    同样的问题也发生在我身上:

    onMenuItemSelected 事件未在 Fragment 中调用

    搜google找不到解决办法,在FragmentActivity中添加onMenuItemSelected方法也没有解决。

    最后参考http://developer.android.com/guide/topics/ui/actionbar.html解决

    注意:如果您通过 Fragment 类的 onCreateOptionsMenu 回调从片段添加菜单项,那么当用户选择片段的其中一项时,系统会为该片段调用相应的 onOptionsItemSelected() 方法。然而,Activity 有机会首先处理事件,因此系统在为 Fragment 调用相同的回调之前对 Activity 调用 onOptionsItemSelected()。

    这意味着只有在活动的 onOptionsItemSelected() 中没有该菜单项处理程序时,才会调用片段上的 onOptionsItemSelected()。

    代码如下 -----删除FragmentActivity上R.action.add的处理程序):

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    
        switch (item.getItemId()) {
            case android.R.id.home:
                popBackStack();             
                return true;        
            case R.id.action_search:
                searchAction();
                return true;
            case R.id.action_logout:
                userLogout();
                return true;
            //case R.id.action_add:
                //return true;    
            default:
                return super.onOptionsItemSelected(item);
        }   
    }
    

    R.action.add 在 Fragment 上的处理程序如下所示:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    
        Log.d("onOptionsItemSelected","yes");
        switch (item.getItemId()) {
            case R.id.action_add:
                add();
                return true;    
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    

    最后记得添加

        setHasOptionsMenu(true);
    

    在 Fragment 的 onCreate 方法中

    【讨论】:

    • 对我来说,为了拦截菜单点击片段,我必须在 FragmentActivity 的 onOptionsItemSelected 和片段的 onOptionsItemSelected 上返回“false”,执行所需的行为。跨度>
    • 带有 setHasOptionsMenu(true) 的片段;在 onCreate 和 public boolean onOptionsItemSelected(MenuItem item) {} 方法中做了魔术
    • @Felixqk 我在使用 Fragments 时遇到了这样的问题。我有两个片段。但是片段 2 的 OnOptionsSelectedItem 没有被调用。片段 2 显示片段 1 的菜单选项。
    • @Roon13 删除 super.onCreateOptionsMenu;来自片段的 onCreateOptionsMenu。 + setHasOptionsMenu(true);在不删除 Activity onOptionsItemSelected 的情况下为我工作。
    【解决方案2】:

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

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

    2. 在 Fragment 中覆盖 onCreateOptionsMenu(Menu menu, MenuInflater inflater)(如果您想在 Fragment 的菜单中执行不同的操作)和 onOptionsItemSelected(MenuItem item) 方法。

    3. 在 Activity 的 onOptionsItemSelected(MenuItem item) 方法中,确保在 Fragment 的 onOptionsItemSelected(MenuItem item) 方法中实现菜单项操作时返回 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;
    }
    

    【讨论】:

    • return false on Activity 的onOptionItemSelected 是关键。只需替换return super.onOptionItemSelected(item);
    • 完美运行。谢谢马可。
    • 很好的答案。当它在片段中时,您应该将 onCreateOptionsMenu(Menu menu) 更改为 onCreateOptionsMenu(Menu menu, MenuInflater inflater)
    • 这是一个很好的解决方案。 Thnakx Marco HC
    • 伟大的解决方案我的朋友!谢谢!
    【解决方案3】:

    我注意到人们给你的解决方案是在活动中实现菜单项的代码,而不是片段。 我认为如果您在片段中实现代码而不是活动,它看起来会更加组织化,因为在我看来它看起来更好。 为此,请执行以下操作:

    活动

    @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            super.onCreateOptionsMenu(menu);
            getMenuInflater().inflate(R.menu.menu, menu);      
            return true;
        }
    
     @Override
        public boolean onOptionsItemSelected(MenuItem item)
        {            
            switch (item.getItemId())
            {
                case R.id.SomeIDInTheMenueOfTheActivity:
                {
                   //something();
                    break;
                }
                default:
                 //do something default and add the code under : 
                 return super.onOptionsItemSelected(item);
            }
            return true;
        }
    

    片段

     @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);  
                setHasOptionsMenu(true);      
            }
    
      @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
        {           
            super.onCreateOptionsMenu(menu, inflater);
        }
    
         @Override
            public boolean onOptionsItemSelected(MenuItem item)
            {
                switch (item.getItemId())
                {           
                    case R.id.SomeIDInFragmentMenue:
                    {             
                        break;
                    }
    
                    default:
                        return super.onOptionsItemSelected(item);
                }
    
                return true;
            }
    

    现在的行(和类似的):“return super.onOptionsItemSelected(item);”在activity和fragment中是超级重要的,因为如果你按照debug中的代码,你会看到首先在Activity上调用menue events函数,如果item与activity的switch中的id不匹配——情况下,默认行:“super.onOptionsItemSelected(item);”如我们所愿,将在片段上调用 ​​onOptionsItemSelected 函数。 (如果您有很多片段,请确保其中也包含该行,因为调用层次结构可能有些复杂)。

    【讨论】:

      【解决方案4】:

      我正在使用 actionbarsherlock。这对我有用:

      1) 创建 dummy_menu.xml 菜单

      <?xml version="1.0" encoding="utf-8"?>
      
      <menu xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="fill_parent" >
      <item
            android:title=""
            android:showAsAction="never"
            android:id="@+id/dummyMenu"
              />
      

      2) 在活动中像这样膨胀菜单:

      @Override
      public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
          com.actionbarsherlock.view.MenuInflater inflater = getSupportMenuInflater();
         inflater.inflate(R.menu.dummy_menu,menu);
         return super.onCreateOptionsMenu(menu);
      }
      

      3) 在片段 onCreateView 调用 setHasOptionsMenu(true) 并覆盖 onCreateOptionsMenu 和 onOptionsItemSelected 也像这样隐藏 dummyMenu(在片段中)

          @Override
      public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
          inflater.inflate(R.menu.fragment_actions, menu);
          MenuItem item = menu.findItem(R.id.dummyMenu);
          item.setVisible(false);
          super.onCreateOptionsMenu(menu, inflater);
      }
      

      希望对某人有所帮助。

      【讨论】:

        【解决方案5】:

        编辑操作栏夏洛克使用

        我不得不使用

        public boolean onMenuItemSelected(int featureId, MenuItem item) {
        

        在主Activity中捕获菜单项

        【讨论】:

        • 同样的问题,它也为我解决了,谢谢。你能说出为什么 onOptionItemSelected 不起作用吗?
        • 因为sherlock动作栏没有使用这个方法
        • 将 onMenuItemSelected 更改为调用 onOptionItemSelected 以便您的代码在从 ABS 移动到 appcompatlib 时可以正常工作
        • @nadeemgc 它不起作用的原因是因为 Android 知道两种类型的菜单:选项菜单和上下文菜单。 Actionbar Sherlock 使用上下文菜单,它调用onContextItemSelected 而不是onOptionsItemSelectedonMenuItemSelected 只是将点击转发到正确的方法,这就是它看起来更好的原因。
        • @AmruE。谢谢,以后会有用。
        【解决方案6】:

        非常简单,您可以在片段中执行此操作,以确保您的操作正确收听:

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

        【讨论】:

          【解决方案7】:

          我遇到了这个问题。那是因为我覆盖了错误的方法

          onOptionsItemSelected(com.actionbarsherlock.view.MenuItem 项) 是我用的。

          确保您使用的是正确的!

          【讨论】:

            【解决方案8】:

            您没有链接到活动方法中的超类。请让onCreateOptionsMenu()返回super.onCreateOptionsMenu(menu),让onOptionsItemSelected()返回super.onOptionsItemSelected(item)(你正在处理的item除外,它应该返回true表示你已经处理了事件)

            【讨论】:

              【解决方案9】:

              您必须在您的活动中添加此代码toolbar.bringToFront(); next set toolbar

               public class MainActivity extends AppCompatActivity {
                   protected void onCreate(Bundle savedInstanceState) {
                      ...
              
                      Toolbar toolbar = findViewById(R.id.toolbar);
                      toolbar.setTitle("Yazd");
                      setSupportActionBar(toolbar);
                      toolbar.bringToFront(); // <<= add here
                       ...
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多