问题 活动中的OnOptionsItemSelected在fragment中的onOptionsItemSelected之前调用。其他方式可能吗?


我有一个活动,可以包含几个片段。每个片段都可以在ActionBar中拥有自己的菜单条目。到目前为止,此工作正常,每个项目都是可点击的,并执行所需的操作。

我的问题如下。在MainActivity中,我声明了以下几行来拦截对ActionBar的HomeIcon的调用:

public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            clearBackStack();
                    setHomeFragment();
            return true;
        default:
            return super.onOptionsItemSelected(item);

        }
    }

我在Activity中声明它,因为我希望每个Fragment都应该调用它,这样我就不必捕获每个片段中的android.R.id.home情况。

在一个片段中,我使用的是setDisplayHomeAsUpEnabled(true),这样我就可以获得ActionBar图标左侧的小箭头。当在这个片段中单击HomeIcon时,我不想设置HomeFragment,我想设置上次显示的片段。所以我有一个onOptionsItemSelected - 片段中的方法:

@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {

    switch (menuItem.getItemId()) {
    case android.R.id.home:
        setLastFragment();
               return true;
    ...

但是,这并不像我希望的那样工作。首先调用Activity的onOptionsItemSelected,捕获MenuItem并重定向到HomeFragment。使用在其他片段中声明的其他MenuItem,我可以检查看到相同的行为。首先调用Activity,不捕获MenuItem(默认情况),然后重定向到super.onOptionsItemSelected(item)。

因此,Android处理菜单点击的情况似乎就是这样。第一个活动,然后是片段。有没有办法改变这个?我不想把android.R.id.home-case放在每个片段中并在那里处理它。有没有更好的方法来做到这一点?


7015
2018-05-21 21:37


起源



答案:


根据开发人员的参考,

“返回false以允许正常的菜单处理继续进行,真的在这里使用它。”

所以我会在Activity的onOptionsItemSelected()实现中默认返回'false',这样事件就会被传递给Fragment的实现,如果它没有被捕获的话。


4
2017-07-20 22:41



这不是MrHill所要求的!我面临着同样的问题。通常,活动处理“Home UP”按钮。有时我们想要在某个片段当前处于活动状态时按下“Home UP”按钮时执行特殊操作。在Activity onOptionsItemSelected上返回false会阻止活动处理该案例。 - John


答案:


根据开发人员的参考,

“返回false以允许正常的菜单处理继续进行,真的在这里使用它。”

所以我会在Activity的onOptionsItemSelected()实现中默认返回'false',这样事件就会被传递给Fragment的实现,如果它没有被捕获的话。


4
2017-07-20 22:41



这不是MrHill所要求的!我面临着同样的问题。通常,活动处理“Home UP”按钮。有时我们想要在某个片段当前处于活动状态时按下“Home UP”按钮时执行特殊操作。在Activity onOptionsItemSelected上返回false会阻止活动处理该案例。 - John


我刚刚遇到这个问题,我使用以下代码使其工作。 在活动中 onOptionsItemSelected功能,添加:

if (id == android.R.id.home){
        Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.container);
        if(null != currentFragment && currentFragment.onOptionsItemSelected(item)){
            return true;
        }
    }

并在片段中 onOptionsItemSelected 方法,你处理相应的事情。 这样,如果片段对菜单项有任何操作,它将执行此操作并返回true以停止任何其他进程。 如果片段与此项没有任何关系,它将返回false或调用super.onOptionsItemSelected方法,该方法最终可能返回false以让其他人处理它。


10
2018-05-01 12:43



这应该是公认的答案...... - Michael Gabay


不确定是否可能。在这里提供的官方文档中:

http://developer.android.com/guide/topics/ui/actionbar.html#ActionEvents

有一条说明,说明如下:

[...]但是,活动有机会首先处理事件,因此系统首先在活动上调用onOptionsItemSelected(),然后再调用片段的相同回调。


1
2018-04-08 14:03



它 是 如果你打电话,可能 setHasOptionsMenu(true) 在早期的部分 Fragment的生命周期,例如在 onCreateView() - Tash Pemhiwa


你可以像@Surely那样写,这是个好主意,但在这种情况下你会打电话 onOptionsItemSelected 片段而不知道它是哪个片段,你应该覆盖 onOptionsItemSelected所有片段中的方法。

如果您只想为特定片段调用此方法,则应按标记找到它们,在添加时使用它们:

case android.R.id.home:
            Fragment frag = getSupportFragmentManager()
                    .findFragmentByTag(FRAGMENT_TAG);

            if(frag != null && frag.isVisible() && frag.onOptionsItemSelected(item)) {
                return true;

标签指定如下:

fragmentManager.beginTransaction()
            .add(containerId, fragment, FRAGMENT_TAG)

0
2017-10-03 15:10