我可以成功截取ActionBar
的{{1}}主页按钮,该按钮会添加到我的NavigationDrawerFragment
,如下所示:
MainActivity
但是,在我的@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!loggedIn() && item.getItemId() == android.R.id.home) {
login();
return true;
}
return super.onOptionsItemSelected(item);
}
ComposeActivity
中,这不起作用。没有在片段上调用ComposeFragment
。
我调试了代码,问题似乎归结为Android支持库的设计。似乎onOptionsItemSelected
和FragmentActivity
都有自己对Activity
的引用。
FragmentManager
首先检查FragmentActivity
是否可以在检查任何碎片之前处理该事件,这与docs一致:
Activity
如下面的代码段所示,/**
* Dispatch context and options menu to fragments.
*/
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
if (super.onMenuItemSelected(featureId, item)) {
return true;
}
switch (featureId) {
case Window.FEATURE_OPTIONS_PANEL:
return mFragments.dispatchOptionsItemSelected(item);
case Window.FEATURE_CONTEXT_MENU:
return mFragments.dispatchContextItemSelected(item);
default:
return false;
}
}
在检查主页按钮或其任何片段是否可以处理该事件后,作为最后的手段处理主页按钮。但是对Activity
的引用不包含任何片段,片段在FragmentManager
的管理器中。因此,如果设置了FragmentActivity
,则Activity
类会吞下该事件。
ActionBar.DISPLAY_HOME_AS_UP
事实证明,作为我的应用程序的根目录并使用导航抽屉的public boolean onMenuItemSelected(int featureId, MenuItem item) {
/* ... */
if (onOptionsItemSelected(item)) {
return true;
}
if (mFragments.dispatchOptionsItemSelected(item)) {
return true;
}
if (item.getItemId() == android.R.id.home && mActionBar != null &&
(mActionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
if (mParent == null) {
return onNavigateUp();
} else {
return mParent.onNavigateUpFromChild(this);
}
}
return false;
/* ... */
}
没有设置此标志,因此不会吞下该事件。但我的MainActivity
有父活动,我需要设置此标志,因此无法拦截操作栏主页按钮。
总结问题:无法拦截点击 操作栏主页按钮来自活动中的片段与 DISPLAY_HOME_AS_UP设置。
这是支持库中的一个错误吗?如果我针对以后的Android版本并删除了支持库,它看起来不会发生。
关于这方面的解决方法,我想我可以:
ComposeActivity
的{{1}}我可以手动将事件传递给我的每个片段,看看他们是否可以在调用super之前处理它。ComposeActivity
中的onMenuItemSelected并执行相同的操作。之前有人遇到过这个吗?我应该在某处记录错误吗?关于这个问题的任何其他想法?
答案 0 :(得分:4)
正如您所解释的,由于在Android中调度事件的流程,似乎子片段永远不会拦截事件,因为它首先被Activity占用。
这是一种解决方法,但我正在做的是将事件传递给子片段,然后再在Activity中处理。
在活动中:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Due to a problem of not being able to intercept android.R.id.home in fragments,
// we start passing the event to the currently displayed fragment.
// REF: http://stackoverflow.com/questions/21938419/intercepting-actionbar-home-button-in-fragment
final Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.XXXXXXX);
if (currentFragment != null && currentFragment.onOptionsItemSelected(item)) {
return true;
}
switch (item.getItemId()) {
case XXX:
...
return true;
case YYY:
...
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}