Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Емкость/переполнение ActionBar не меняется при изменении ориентации

Автор вопроса: Chris BoyleОтветов: 3

У меня есть приложение, использующее 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>

При запуске это работает правильно:

Альбомная: широкая панель действий со всеми элементами

Портрет: узкая панель действий с переполнением(да, я мог бы заставить все элементы всегда отображаться, и они подходили бы, как показано ниже, но это может сломаться на планшете меньшего размера)

Когда эмулятор меняет ориентацию, емкость панели действий не меняется:

Портрет, когда я начал в альбомной ориентации: сузить панель действий со всеми элементами(это нормально, но непоследовательно)

Пейзаж, когда я начал в портретной ориентации: широкая панель действий с переполнениемЭто выглядит очень глупо, поэтому я хотите это исправить.

Я добавил этот вызов в invalidateOptionsMenu(), но он не помогает:

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

(На самом деле я вызываю его отражением для обратной совместимости, но отладчик говорит мне, что он действительно вызывается и не сталкивается с исключением.)

invalidateOptionsMenu() на самом деле вызывает onCreateOptionsMenu() (который повторно наполняет меню) перед возвратом, и я вижу внутри последнего, что getResources().getConfiguration().ориентация уже изменилась. Так что это действительно озадачивает. Если меню параметров воссоздается, когда ориентация изменилась, это должен быть сам ActionBar, кэширующий ширину?

Есть ли способ воссоздать ActionBar без уничтожения/создания Activity? (поскольку последнее в моем случае немного дороже)

Изменить: вот минимальный пример проекта, показывающий проблему .

Редактировать 2: я подумал о проверке ширины экрана и программной настройке флагов showAsAction между всегда и никогда надлежащим образом, но для этого нужно знать (или угадывать) ширину каждого элемента. общедоступный API ActionBar не помогает мне в этом вопросе.

  • Можете ли вы создать и опубликовать полный образец проекта, демонстрирующий проблему? Кроме того, вы пробовали это на оборудовании? Возможно, это проблема конкретного эмулятора. CommonsWare 02.10.2011
  • @CommonsWare Хорошо, посмотрите мое редактирование в конце примера проекта. В настоящее время у меня нет планшетного оборудования, но я собираюсь посетить мероприятие Android Developer Lab, посвященное планшетам, в среду, поэтому я, вероятно, смогу попробовать его там. Chris Boyle 02.10.2011
  • Я могу воспроизвести проблему на XOOM под управлением Android 3.2. Это похоже на ошибку. Я пошел дальше и зарегистрировал проблему: code.google.com. /p/android/issues/detail?id=20493 CommonsWare 02.10.2011

androidandroid-layoutandroid-actionbarandroid-menu

Ответы

Ответ 1 · рейтинг 6 · danielnilsson9

Я столкнулся с этой проблемой и придумал хак, который работает на 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));

Не очень красивое решение, но оно работает.

Ответ 2 · рейтинг 2 · Chris Boyle

Я осторожно работал над этим: когда ширина устройства превышает 850dip, принудительно отображать все элементы в панели действий, в противном случае продолжайте позволять платформе решать.

Вот коммит git. Изменить: и последующую фиксацию для исправления с помощью слишком новое поле, упс. :-)

Я определенно все еще заинтересован в лучших ответах (кроме ожидания исправления для платформы).

Ответ 3 · vaughandroid

Я обнаружил, что самым простым и эффективным решением было очистить меню, а затем перестроить его.

Например:

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы