2011-10-02 5 views
7

Ho un app utilizzando l'ActionBar, dove mi occupo di me stesso orientamento cambia:ActionBar Capacità/troppo pieno non cambiare sul cambiamento dell'orientamento

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

... e il menu dovrebbe inserirsi nel ActionBar senza troppopieno nel paesaggio, ma non in verticale:

<?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> 

all'avvio, questo funziona correttamente:

Paesaggio: wide ActionBar with all items in

Ritratto: narrow ActionBar with overflow (sì, ho potuto costringere tutti gli elementi da visualizzare sempre e si adatterebbe, come mostrato di seguito, ma che potrebbe rompere su una tavoletta più piccola)

Quando l'emulatore cambia orientamento, l'ActionBar del capacità non sembra cambiare:

Ritratto, quando ho iniziato nel paesaggio: narrow ActionBar with all items in (questo è ok, ma incoerente)

Lan dscape, quando ho iniziato in verticale: wide ActionBar with overflow Questo sembra davvero sciocco ed è la ragione per cui voglio sistemarlo.

ho aggiunto questa chiamata a invalidateOptionsMenu(), ma non aiuta:

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

(In realtà io lo chiamo dalla riflessione per la compatibilità a ritroso, ma il debugger mi dice che in realtà si chiama e non lo fa incontro un'eccezione.)

invalidateOptionsMenu() finisce di chiamata onCreateOptionsMenu() (che ri-gonfia menu) prima di tornare, e posso vedere all'interno di quest'ultimo che getResources(). getConfiguration(). orientamento è già cambiato. Quindi questo è davvero sconcertante. Se il menu delle opzioni viene ricreato, quando l'orientamento è cambiato, deve essere ActionBar stesso che memorizza nella cache la larghezza?

C'è un modo per ricreare l'ActionBar senza distruggere/creare l'attività? (perché quest'ultimo è un po 'caro a mio caso)

Edit: Ecco un minimal sample project che mostra il problema.

Edit 2: avevo pensato di controllare la larghezza dello schermo e la programmazione regolare le bandiere showAsAction tra sempre e mai in modo appropriato, ma che richiede la conoscenza (o indovinare) la larghezza di ogni elemento. ActionBar's public API non mi aiuta su questo punto.

+0

Puoi creare e inviare un progetto di esempio completo che dimostra il problema? Inoltre, hai provato questo su hardware? È possibile che si tratti di un problema specifico dell'emulatore. – CommonsWare

+0

@CommonsWare Ok, vedi la mia modifica alla fine per il progetto di esempio. Al momento non ho l'hardware del tablet, ma vado all'evento Android Developer Lab sui tablet mercoledì, quindi posso presumibilmente provarlo lì. –

+1

Posso riprodurre il problema su un XOOM con Android 3.2. Questo sembra un insetto. Sono andato avanti e ho presentato un problema per questo: http://code.google.com/p/android/issues/detail?id=20493 – CommonsWare

risposta

2

Ho lavorato con cautela intorno a questo: quando la larghezza del dispositivo è maggiore di 850dip, forza la visualizzazione di tutti gli elementi in ActionBar, altrimenti continua a lasciare decidere la piattaforma.

Here's the git commit. Modifica: e follow-up commit da correggere utilizzando un campo troppo nuovo, oops.:-)

Sono sicuramente ancora interessato a risposte migliori (oltre ad aspettare una correzione per la piattaforma).

5

Mi sono imbattuto in questo problema e ho trovato un trucco che funziona al 100%.

Ho attivato chiamando invalidateOptionsMenu() due volte. Guarda il codice qui sotto:

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(); 

} 

E nel tuo onCreateOptionsMenu() Impostare questo su di voi MenuItems si desidera mostrare:

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

Non è una bella soluzione, ma funziona.

1

Ho trovato che la soluzione più semplice ed efficace era quella di cancellare il menu e quindi ricostruirlo.

Ad esempio:

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