Fragment的onOptionsItemSelected方法没有被调用。

38

我的Fragment将父Activity选项替换为特定的选项条目,但当我单击该选项时,仅调用Activity的onOptionItemSelected方法,尽管我已在Fragment中覆盖了该方法。我有什么遗漏吗?

Fragment的方法:

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

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    Log.d(TAG, "Fragment.onCreateOptionsMenu");

    if (mPasteMode) {
        menu.clear();
        inflater.inflate(R.menu.contexual_paste, menu);
        getActivity().getActionBar().setTitle("PasteMode");
    }
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    Log.d(TAG, "Fragment.onOptionsItemSelected");

    switch (item.getItemId()) {
        case R.id.context_action_paste:
            Toast.makeText(getActivity(),
                     "It worked ",
                    Toast.LENGTH_SHORT).show();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

活动的方法:

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    Log.d(TAG, "MainActivitiy.onOptionsItemSelected");
    switch (item.getItemId()) {
        case R.id.action_refresh:
            Toast.makeText(this, "Action Refresh selected", Toast.LENGTH_SHORT).show();
            break;
        default:
            break;
    }
    return true;
}

Logcat输出:

MainActivity.onCreateOptionsMenu
Fragment.onCreateOptionsMenu
MainActivitiy.onOptionsItemSelected

那我该如何调用片段的 onOptionsItemSelected 方法呢?

7个回答

64
如果您的Activity的onOptionsItemSelected方法返回true,则该调用在Activity中被消耗,Fragment的onOptionsItemSelected不会被调用。所以,在您的Activity的onOptionsItemSelected方法中返回false或通过super.onOptionsItemSelected调用父类实现来返回(默认实现返回false)。
根据Activity类的javadoc文档,Activity.onOptionsItemSelected方法应该:
“返回false以允许正常的菜单处理继续进行,返回true以在此处消耗它。”

2
非常感谢,你节省了我的时间。 - Farmer
1
你是完全正确的!只需在MainActivity中使 onOptionsItemSelected 返回 false,一切都会按预期工作。 - Aliton Oliveira

58

在Activity方法中,您没有调用超类。请在onCreateOptionsMenu()方法中加入super.onCreateOptionsMenu(menu)代码,并在onOptionsItemSelected()方法中加入super.onOptionsItemSelected(item)代码(除了您正在处理的项目,该项目应该返回true以表示您已经处理了事件)。


20
请注意,在片段中必须调用setHasOptionsMenu(true),才能为“isOptionsMenuCreated”返回正确的结果。 - Tash Pemhiwa

17

在我的情况下,我没有添加任何菜单项(即我没有在活动或片段中调用onCreateOptionsMenu)。然而,我需要在片段中使用操作栏主页(向上)按钮。为此,我必须确保在片段的onCreateView()方法中调用了setHasOptionsMenu(true),然后才能使其工作。然后,我就不需要在我的活动中覆盖onOptionsItemSelected了。


setHasOptionsMenu(true) 是解决方法,谢谢。 - Goran Horia Mihail

3
经过几个小时的解决,我找到了一个解决方案。
你需要在activity中调用onOptionsItemSelected,但是像这样返回false。

override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return false
    }

下一步是在 fragment onCreate() 中添加 setHasOptionsMenu(true)

最后,您可以在片段中调用 onOptionsItemSelected 并处理菜单项点击

override fun onOptionsItemSelected(item: MenuItem): Boolean {
        //My awesome stuff
        return super.onOptionsItemSelected(item)
    }

就是这样。


1
我找到了解决方案,即:

Fragment.class

 @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // Do something that differs the Activity's menu here
    //MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.wifinity_setting, menu);
    for (int i = 0; i < menu.size(); i++) {
        MenuItem item = menu.getItem(i);
        SpannableString spanString = new SpannableString(menu.getItem(i).getTitle().toString());
        spanString.setSpan(new ForegroundColorSpan(Color.BLACK), 0, spanString.length(), 0); //fix the color to white
        item.setTitle(spanString);
    }
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {

        case R.id.menu1:
            Intent intent3 = new Intent(context, activity.class);
            startActivity(intent3);
            return true;

    }
    return true;
}

ACtivity.class

覆盖onOptionsItemSelected()方法 //当选项被选中时,片段的onOptionselected方法会被调用.. 这个解决方案对我有效

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        default:
            if(fragment != null)
                fragment.onOptionsItemSelected(item);
    }
    return true;
}

0

我同意目前被接受的解决方案,但另一个可能的原因是存在模糊的类引用。我的项目中有一个自定义类名为MenuItem,而我的Fragment将custom.MenuItem解释为参数类型,而不是android.view.MenuItem。

症状是我的Override上出现了红色波浪线,并且IDE消息指示onOptionsItemSelected将不会被调用。


0
if you are using view binding in your fragment you can populate menu using below code 

in your onCreate method use 

step 1 setHasOptionsMenu(true)
step 2 inflate menu by like below binding.actionBar.toolbar.inflateMenu(R.menu.home_screen_menu)

step 3 binding.actionBar.toolbar.setOnMenuItemClickListener {
            onOptionsItemSelected(it)
        }

then override 
override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
           case 1{}
           case 2{}
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接