ActionBar容量/溢出量不会改变方向变化

时间:2011-10-02 11:02:30

标签: android android-layout android-actionbar android-menu

我有一个使用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>

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

风景: wide ActionBar with all items in

人像: narrow ActionBar with overflow (是的,我可以强制所有项目始终显示,并且它们适合,如下所示,但可能会在较小的平板电脑上打破)

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

肖像,当我开始在风景中: narrow ActionBar with all items in (这没关系,但不一致)

风景,当我开始画像时: wide ActionBar with overflow 这看起来非常愚蠢,这也是我想解决这个问题的原因。

我将此调用添加到invalidateOptionsMenu(),但它没有帮助:

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

(实际上我通过反射调用它来实现向后兼容性,但调试器告诉我它确实被调用并且没有遇到异常。)

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

有没有办法在不破坏/创建活动的情况下重新创建ActionBar?(因为后者在我的情况下有点贵)

修改:这是显示问题的minimal sample project

编辑2:我曾想过检查屏幕宽度并以编程方式调整showAsAction标志之间总是永远不合适,但这需要知道(或猜测)每个项目的宽度。 ActionBar's public API在这一点上对我没有帮助。

3 个答案:

答案 0 :(得分:5)

我遇到了这个问题并想出了一个可以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()中设置你想要显示的菜单项:

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

不是一个漂亮的解决方案,但它有效。

答案 1 :(得分:2)

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

Here's the git commit修改follow-up commit修复使用太新的字段,oops。 : - )

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

答案 2 :(得分:0)

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

例如:

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.
    }
}