ActionBar容量/溢出没有改变方向的变化

我有一个应用程序使用ActionBar,我自己处理方向的变化:

android:configChanges="keyboard|keyboardHidden|orientation|screenSize" 

…和菜单应适合在ActionBar没有横向溢出,但不是肖像:

 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:title="@string/Game" android:id="@+id/game" android:icon="@android:drawable/ic_menu_manage" android:showAsAction="ifRoom|withText"/> <item android:title="@string/Type" android:id="@+id/type" android:icon="@android:drawable/ic_menu_edit" android:showAsAction="ifRoom|withText"/> <item android:title="@string/Other" android:id="@+id/other" android:icon="@android:drawable/ic_menu_gallery" android:showAsAction="ifRoom|withText"/> <item android:title="@string/Solve" android:id="@+id/solve" android:icon="@android:drawable/ic_menu_directions" android:showAsAction="ifRoom|withText"/> <item android:title="@string/Help" android:id="@+id/help" android:icon="@android:drawable/ic_menu_help" android:showAsAction="ifRoom"/> </menu> 

在启动时,这可以正常工作:

景观: 与所有项目在广泛的ActionBar

肖像: 狭窄的ActionBar溢出 (是的,我可以强制所有项目始终显示,他们将适合,如下所示,但可能会在一个较小的平板电脑上打破)

当模拟器改变方向时,ActionBar的容量似乎没有改变:

肖像,当我开始在风景: 与所有项目在狭窄的ActionBar (这是好的,但不一致)

风景,当我开始肖像: 宽泛的ActionBar溢出 这看起来非常愚蠢,是我想解决这个问题的原因。

我把这个调用添加到invalidateOptionsMenu() ,但是没有帮助:

 @Override public void onConfigurationChanged(Configuration newConfig) { maybeMoveSomeViewsAround(newConfig); super.onConfigurationChanged(newConfig); invalidateOptionsMenu(); } 

(其实我是通过向后兼容的reflection来调用它,但是debugging器告诉我它真的被调用,并且不会遇到exception。)

invalidateOptionsMenu()实际上在返回之前最终调用了onCreateOptionsMenu()(这会重新充气菜单),并且我可以在后面看到getResources()。getConfiguration()。orientation已经改变。 所以这真是令人费解。 如果正在重新创build选项菜单,当方向改变时,它必须是ActionBar本身caching的宽度?

有没有办法重新创buildActionBar而不销毁/创build活动? (因为后者在我的情况下有点贵)

编辑:这是一个最小的示例项目显示的问题。

编辑2:我曾经想过检查屏幕宽度和编程调整showAsAction标志之间永远和从来没有适当的,但是这需要知道(或猜测)每个项目的宽度。 ActionBar的公共API在这一点上帮不了我。

我遇到了这个问题,并提出了100%的黑客工作。

我主张两次调用invalidateOptionsMenu()。 看下面的代码:

 private boolean hackActionBarReset = false; @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); //a hack to reset the items in the action bar. hackActionBarReset = true; invalidateOptionsMenu(); hackActionBarReset = false; invalidateOptionsMenu(); } 

并在你的onCreateOptionsMenu()设置你想要显示的menuitems:

 item.setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT | (hackActionBarReset ? MenuItem.SHOW_AS_ACTION_NEVER : MenuItem.SHOW_AS_ACTION_IF_ROOM)); 

不是一个漂亮的解决scheme,但工作。

我小心翼翼地解决了这个问题:当设备的宽度大于850dip时,强制显示ActionBar中的所有项目,否则继续让平台决定。

这是git commit 。 编辑:和后续承诺修复使用太新的领域,哎呀。 🙂

我肯定仍然对更好的答案感兴趣(除了等待修复平台)。

我发现最简单和最有效的解决方法是清除菜单,然后重build它。

例如:

 Menu menu; @Override public boolean onCreateOptionsMenu(Menu menu) { this.menu = menu; // Setup code goes here... } @Override public void onOrientationChanged() { if (menu != null) { menu.close(); // Ensure the menu is closed before changing its contents. menu.clear(); onCreateOptionsMenu(menu); // Rebuild the menu. } }