我可以成功拦截ActionBar
我的主页按钮NavigationDrawerFragment
,它被添加到我的MainActivity
,像这样:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!loggedIn() && item.getItemId() == android.R.id.home) {
login();
return true;
}
return super.onOptionsItemSelected(item);
}
然而,在我的ComposeActivity
with ComposeFragment
这是行不通的。onOptionsItemSelected
没有在片段上调用。
我已经调试了代码,问题似乎归结为Android支持库的设计。看来两者FragmentActivity
and Activity
有自己的参考文献FragmentManager
.
FragmentActivity
首先检查是否Activity
可以在检查事件的任何片段之前处理该事件,这与docs http://developer.android.com/guide/topics/ui/actionbar.html#ActionEvents:
/**
* 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
is set.
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
,作为我的应用程序的根并使用导航抽屉,没有设置此标志,因此没有吞咽该事件。但我的ComposeActivity
有一个父活动,我需要设置此标志,这样就不可能拦截操作栏主页按钮。
总结一下这个问题:无法拦截点击
来自活动中片段的操作栏主页按钮
DISPLAY_HOME_AS_UP 设置。
那么这是支持库中的错误吗?如果我瞄准更高版本的 Android 版本并放弃支持库,看起来不会发生这种情况。
关于这个问题的解决方法,我想我可以:
- In my
ComposeActivity
's onOptionsItemSelected
我可以手动将事件传递给每个片段,看看它们是否可以在调用 super 之前处理它。
- 覆盖 onMenuItemSelected 在
ComposeActivity
并做同样的事情。
以前有人遇到过这个吗?我应该在某处记录错误吗?解决这个问题还有其他想法吗?