Dienstag, 22. Mai 2012

ActionBar

Die Menu-Steuerung in Android ist ein interessantes Beispiel dafür, wie die Entwickler des Systems auf Erfahrungen mit der Verwendung des Systems eingehen. Ursprünglich – vor 3.0 - wurde das Options-Menu so wichtig erachtet, dass dafür sogar eine eigene Taste spendiert wurde. Das Menu wurde als reines Popup-Menu realisiert. Schon der Name spricht dafür, dass dieses Menu in erster Linie dazu gedacht war, Einstellungen für die App vorzunehmen. Es stellte sich allerdings heraus, dass viele Anwendungen das Options-Menu dazu missbrauchten, Navigationen zu realisieren.
Ab 3.0 wurde das Konzept überarbeitet – wobei sicherlich auch die Tatsache von Bedeutung war, dass diese Version speziell für Tablets vorgesehen und damit reichlich Platz auf dem Screen vorhanden war. Die Action-Bar als vollkommen neues Element wurde eingeführt und das bisherige Options-Menu in diese Komponente integriert. Die Action-Bar ist als fester Bestandteil per Default immer am Screen sichtbar (kann aber auch deaktiviert werden). Ab Android 4.0 ist die Action-Bar dann auch Bestandteil der Smartphone-Variante des Betriebssystems. Die Menu-Taste ist damit kein Pflichtelement eines Smartphones mehr.
Die ActionBar ist im wesentlichen in 4 Bereiche unterteilt („App-Icon“, „View-Control“, „Action-Buttons“ und „Action-Overflow“), wobei die Darstellung konfigurierbar ist und auch davon abhängig, wie viel Platz auf dem aktuellen Gerät zur Verfügung steht. So kann der „View-Control“-Bereich in einer zusätzlichen Zeile unterhalb der Haupt-ActionBar dargestellt werden (wie im Bild erkennbar) oder die „Action-Buttons“ verwenden den Platz am Fuß des Bildschirms.
Das „App-Icon“ (im Bild ganz links) soll natürlich in erster Linie dazu dienen, die aktuell laufende App zu identifizieren. Es kann auch dazu verwendet werden, zur „Home“-Activity der App oder einfach „Back“ zu navigieren.
Die „View-Control“ wird zur Navigation innerhalb der App verwendet, beispielsweise um in Form von Tabs verschiedene Seiten (Fragmente) einer Activity zu aktivieren.
Die „Action-Buttons“ (im Bild ganz rechts) kommen dem bisherigen Options-Menu noch am nächsten. Sie sollen dazu dienen, kontextabhängig zusätzliche Aktionen aufzurufen. Für häufige Aktionen kann das direkt per Icon in diesem Bereich erfolgen, weniger häufig benötigte Aktionen können im „Action-Overflow“-Bereich liegen. Wenn das Device eine Menu-Taste besitzt, wird dieser „Action-Overflow“-Bereich durch Klick auf die Taste aktiviert, ansonsten wird ein entsprechende Auswahl-Liste dargestellt.
Nicht nur bezüglich Inhalt und Bedienung lösen die Action-Buttons ab Android 3.0 das Options Menu der vorhergehenden Versionen weitestgehend ab, auch aus Sicht der Programmierung. Der Übergang ist auf dieser Ebene sehr transparent:
Unter 2.x konnte ein Options Menu einfach in der folgenden Form deklariert werden:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
 <item android:id="@+id/mainMenuItem" android:title="@string/main" />
    <item android:id="@+id/layoutDemoMenuItem" android:title="@string/layoutDemo" />
    <item android:id="@+id/layoutDemo2MenuItem" android:title="@string/layoutDemo" />
    <item android:id="@+id/fragmentMenuItem" android:title="@string/fragment" />
</menu>
Methoden zum Anhängen des Options Menu und zur Reaktion auf die Auswahl eines Items werden an der Activity überschrieben. Hier in Form einer BaseActivity, von der alle Activities abgeleitet werden können, die das Options Menu bereitstellen sollen:

public class BaseActivity extends Activity {

     @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  MenuInflater menuInflater = getMenuInflater();
  menuInflater.inflate(R.menu.menu, menu);
  return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  switch (item.getItemId()) {
  case R.id.mainMenuItem:
  case android.R.id.home:
   Log.v(getLocalClassName(), "call main");
   Intent intent = new Intent(this, Workshop4Activity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
   startActivity(intent);
   break;
  case R.id.fragmentMenuItem:
   Log.v(getLocalClassName(), "call fragment");
   startActivity(new Intent(this, FragmentActivity.class));
   break;
  case R.id.layoutDemoMenuItem:
   Log.v(getLocalClassName(), "call layoutDemo");
   startActivity(new Intent(this, LayoutDemoActivity.class));
   break;
  case R.id.layoutDemo2MenuItem:
   Log.v(getLocalClassName(), "call layoutDemo");
   startActivity(new Intent(this, LayoutDemoActivity2.class));
   break;
  }
  return true;
 }
}
Das ist im Trivialfall schon alles.
Um nun unter Android 4.0 die Einträge des Options Menus in der ActionBar erscheinen zu lassen, wird der entsprechende Eintrag in der XML-Datei einfach mit einem Attribute „android:showAsAction“ versehen. Mögliche Werte sind „never“, „always“, „ifRoom“, „withText“ und „collapseActionView“. Diese können auch – falls sinnvoll – mit „|“ verknüpft werden.
Ansonsten ist das schon alles, die BaseActivity bleibt unverändert.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
 <item android:id="@+id/mainMenuItem" android:title="@string/main"
  android:showAsAction="ifRoom|withText" />
    <item android:id="@+id/layoutDemoMenuItem" android:title="@string/layoutDemo"
   android:showAsAction="always" />
    <item android:id="@+id/layoutDemo2MenuItem" android:title="@string/layoutDemo"
  android:showAsAction="ifRoom" />
    <item android:id="@+id/fragmentMenuItem" android:title="@string/fragment"
  android:showAsAction="ifRoom" />
</menu>
Es ist möglich, die „Action-Buttons“ durch kompliziertere Controls zu ersetzen. Die Möglichkeiten sind natürlich immer durch den äußerst geringen Platz begrenzt. Ein ActionProvider ersetzt sogar die komplette Logik. „collapseActionView“ erlaubt dann eine „Kurzdarstellung“, aus der per Klick eine ausführliche Darstellung aufklappt.
Die Navigation im „View-Control“-Bereich der ActionBar ist auch nicht sonderlich kompliziert. Die Entwicklerdokumentation beschreibt das sehr anschaulich (http://developer.android.com/guide/topics/ui/actionbar.html). Dort wird für den Fall, dass die einzelnen Seiten der Navigation als Fragmente realisiert sind, einfach ein ActionBar.TabListener implementiert. Dieser instantiiert bei Bedarf die entsprechenden Fragmente. Jeder „View-Cotrol“-Eintrag der ActionBar wird dann mit dem entsprechenden Listener verknüpft. Schließlich muss nur noch der NavigationMode der ActionBar auf „NAVIGATION_MODE_TABS“ gesetzt werden – in der onCreate-Methode der Activity. Die ContentView der Activity wird nicht gesetzt, hier wird einfach der Default-Container verwendet. Relativ einfach ist es dann auch, statt einer Tab-Navigation einen Spinner zu verwenden. Die Liste der Elemente muss in der entsprechenden Array-Resource abgelegt werden. Und die Auswahl der Elemente wird über einen SpinnerAdapter und einen OnNavigationListener realisiert.

Keine Kommentare:

Kommentar veröffentlichen