片段不接收菜单callback
我有一个片段类,它扩展了Fragment
并调用setHasOptionsMenu
参与菜单。 这个类还实现了onCreateOptionsMenu
, onPrepareOptionsMenu
和onOptionsItemSelected
。
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); .... }
我dynamic加载这个片段使用FragmentTransaction
在我的活动(扩展FragmentActivity
)。
然而没有菜单callback( onCreateOptionsMenu
, onPrepareOptionsMenu
和onOptionsItemSelected
)被调用(我debugging了这些方法中的一些断点),菜单不显示。
我错过了什么吗? 我需要在我的活动中添加一些内容吗?
我正在使用Android兼容性库,使用L11 SDK编译并在Xoom中进行testing。
编辑 :我发现了这个问题。 我的AndroidManifest是针对L11,这似乎隐藏菜单button,并阻止被调用的callback。 但是,如果我从清单中删除了这个,我就会丢失一些我需要的其他function(例如列表中的激活状态)。 有谁知道如何解决这个问题(启用菜单button),而无需从清单中删除targetSdkVersion=11
?
Aromero,不要忘记使用方法的片段版本来覆盖onCreateOptionsMenu,类似如下:
@Override public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.queue_options, menu); super.onCreateOptionsMenu(menu, inflater); }
顺便说一下,这将在片段中进行,并添加到Activity的充气菜单中(如果有的话)。 自己也有同样的问题,直到我明白了这一点。
金
如果你遇到了ActionBarSherlock的这个问题,你需要确保你的碎片是SherlockFragments,而不仅仅是SupportFragments,而你正在重写的是
public void onPrepareOptionsMenu (com.actionbarsherlock.view.Menu menu) {
不
public void onPrepareOptionsMenu (android.view.Menu menu) {
如果你做了后者,你应该得到一些有关函数是最终的警告,你无法覆盖它。 这是一个警告,你正试图重写错误的function!
如果通过将类从SherlockFragment切换到仅仅片段来修复错误,则可以创build该函数。 。 。 但它不会被调用。
我有同样的问题,但我认为最好总结和介绍最后一步,使其工作:
-
在你的Fragment的
onCreate(Bundle savedInstanceState)
方法中添加setHasOptionsMenu(trueonCreate(Bundle savedInstanceState)
方法。 -
在你的Fragment中覆盖
onCreateOptionsMenu(Menu menu, MenuInflater inflater)
(如果你想在Fragment的菜单中做一些不同的事情)和onOptionsItemSelected(MenuItem item)
方法。 -
在
onOptionsItemSelected(MenuItem item)
Activity的方法中,确保在onOptionsItemSelected(MenuItem item)
Fragment的方法中实现菜单项目操作时返回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) { // 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; }
我希望这会有所帮助。
干杯。
如果你有一个活动和一个片段,每个都加载菜单项,那么你需要特别注意你使用的覆盖。
活动可以覆盖onOptionsItemSelected和onMenuItemSelected ,但片段只能覆盖onOptionsItemSelected 。
如果您在您的活动中覆盖onMenuItemSelected并在您的片段中覆盖onOptionsItemSelected ,则您的片段覆盖将永远不会被触发。
而是在activity和fragment中使用onOptionsItemSelected 。
你需要确保你调用setHasOptionsMenu(true);
在片段中调用onCreate
或onCreateView
。
您还需要在片段中实现onCreateOptionsMenu
的覆盖。
另一种可能的情况是,当你在每个片段中使用一个公共的动作时, 例如R.id.action_add
今天我有这样的情况:点击选项菜单[add]被调用了“错误” onOptionItemSelected
因为每个片段(使用DrawerLayout
dynamicreplace)具有相同的R.id.action_add
。
简短的故事,如果你有这样的情况总是检查你的片段是可见的:
if (!isVisible()) return false;
onOptionItemSelected
,关注onOptionItemSelected
链!
MainActivity | | onOptionItemSelected +----------------------- | return false | MyCoolFragment1 | | onOptionItemSelected +----------------------- | return false | MyCoolFragment2 | | onOptionItemSelected +----------------------- | return true | [item selection handled]
如果你添加你的片段(如下所示):
getSupportFragmentManager() .beginTransaction() .replace(R.id.content_frame, MyCoolFragment1.newInstance()) .commit()
并且你已经为每个片段中的一个普通的动作(比如R.id.action_add)定义了相同的ID; 不要忘记添加这一行到每个:if(!isVisible())返回false;
@Override public boolean onOptionsItemSelected(MenuItem item) { if (!isVisible()) return false; // <-- Not visible? skip! if (item.getItemId() == R.id.action_add) { //.TODO whatever return true; //.Handled! } return false; //.Skip }
当我将ViewPagerIndicator与ActionBarSherlock结合使用时遇到了这个问题。 虽然看起来这是固定的,但我仍然遇到了这个问题。 我发现的工作是手动调用片段。
@Override public boolean onOptionsItemSelected(MenuItem item) { Toast.makeText(this, "From activity", Toast.LENGTH_SHORT).show(); // TODO Fragment currentFragment = mAdapter.getItem(mPager.getCurrentItem()); if (currentFragment != null && currentFragment instanceof SherlockFragment) { ((SherlockFragment)currentFragment).onOptionsItemSelected(item); } return super.onOptionsItemSelected(item); }
我发现了这个问题。 AndroidManifest是针对SDK 11,这似乎隐藏菜单button,并阻止被调用的callback。 我认为这打破了似乎被Android 3.0中的操作栏所取代的菜单button的兼容性
我认为你已经实现了onCreateOptionsMenu
, onPrepareOptionsMenu
和onOptionsItemSelected
在extends Fragment
的类中。 在你正在加载这个片段的Activity类中这样做
从android开发人员网站 – 链接
注意:如果通过Fragment类的onCreateOptionsMenu()callback从片段中充填菜单项,则当用户select其中一个项目时,系统将调用onOptionsItemSelected()。 但是,活动首先有机会处理事件,因此系统首先在活动上调用onOptionsItemSelected(),然后调用该片段的相同callback 。 为了确保活动中的任何片段也有机会处理callback,总是将调用作为默认行为传递给超类,而不是在不处理该项时返回false 。
所以Marco HC是最好的答案。
我有同样的问题和解决scheme,为我工作是:
-
删除或注释任何onOptionsItemSelected(),onMenuItemSelected(),甚至onPrepareOptionMenu(),并保留在Activity onCreateOptionsMenu()中:
@Override public boolean onCreateOptionsMenu(Menu menu){ MenuInflater inflater=getMenuInflater(); inflater.inflate(R.layout.menu, menu); return true; }
-
在片段类中,在onCreateView()中,把:
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.action_insert: //doing stuff return true; } return false; }
经过testing,并在Android 4.4上工作
如果您的工具栏在父活动xml中定义,请确保在您的片段中执行此操作
@Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { .... Toolbar toolbar = (Toolbar)getActivity().findViewById(R.id.toolbar); ((AppCompatActivity)getActivity()).setSupportActionBar(toolbar); setHasOptionsMenu(true); }
然后,当然,像下面覆盖onCreateOptionsMenu
@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.edit_menu, menu); super.onCreateOptionsMenu(menu, inflater); }
这是为我工作的唯一解决scheme!