Емкость / переполнение ActionBar не меняется при изменении ориентации - PullRequest
7 голосов
/ 02 октября 2011

У меня есть приложение, использующее панель действий, где я самостоятельно обрабатываю изменения ориентации:

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 (). Уже изменилась. Так что это действительно загадочно. Если меню опций воссоздается, когда ориентация изменилась, это должен быть сам ActionBar, кэширующий ширину?

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

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

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

Ответы [ 3 ]

5 голосов
/ 05 июля 2012

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

Я осторожно обходил это: когда ширина устройства превышает 850 dip, принудительно отображайте все элементы в ActionBar, в противном случае продолжайте разрешать платформе решать.1004 *. Редактировать: и последующий коммит для исправления с использованием слишком нового поля, упс.: -)

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

0 голосов
/ 08 января 2013

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

Например:

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