【问题标题】:ActionBar capacity/overflow not changing on orientation changeActionBar 容量/溢出不随方向变化而变化
【发布时间】:2011-10-02 11:02:29
【问题描述】:

我有一个使用 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 的容量似乎没有改变:

纵向,当我从横向开始时: (这没问题,但不一致)

横向,当我开始纵向时: 这看起来很傻,这就是我想要解决这个问题的原因。

我将此呼叫添加到 invalidateOptionsMenu(),但没有帮助:

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

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

invalidateOptionsMenu() 实际上最终会在返回之前调用 onCreateOptionsMenu() (它会重新膨胀菜单),我可以在后者内部看到 getResources().getConfiguration().orientation 已经改变。所以这真的很令人费解。如果重新创建选项菜单,当方向改变时,一定是ActionBar自己缓存宽度?

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

编辑:这是一个 minimal sample project 显示问题。

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

【问题讨论】:

  • 您能否创建并发布一个完整的示例项目来演示该问题?另外,你在硬件上试过吗?这可能是特定于模拟器的问题。
  • @CommonsWare 好的,请在最后查看我对示例项目的编辑。我目前没有平板电脑硬件,但我周三要去参加有关平板电脑的 Android 开发者实验室活动,所以我大概可以在那里试一试。
  • 我可以在运行 Android 3.2 的 XOOM 上重现该问题。这感觉就像一个错误。我已经为它提交了一个问题:code.google.com/p/android/issues/detail?id=20493

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


【解决方案1】:

我遇到了这个问题并想出了一个 100% 有效的 hack。

我已经调用了两次 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));

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

【讨论】:

    【解决方案2】:

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

    Here's the git commit编辑:follow-up commit 修复使用太新的字段,哎呀。 :-)

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

    【讨论】:

      【解决方案3】:

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

      例如:

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

      【讨论】:

      • 你不需要这样做。只需使用invalidateOptionsMenu()
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多