ActionBarSherlock ermöglicht die Nutzung des ActionBar-API unter älteren Android-Versionen

Der Detektiv in der Action Bar
Kommentare

Betrachtet man aktuelle Apps von Google wie den Play Store, Google Talk oder auch Google Plus als Vorbilder für ein angemessenes Design, so fällt auf, dass sich alle in einem Punkt ähneln: Die Navigation wird einheitlich über die ActionBar realisiert. Soll dieses Pattern für die eigene App zum Einsatz kommen, ohne dabei Nutzer älterer Android-Versionen auszuschließen, führt kein Weg an ActionBarSherlock vorbei. Bei der Verwendung sind jedoch einige Punkte zu berücksichtigen, damit sich die Zusammenarbeit mit dem Detektiv nicht zu einem kniffeligen Fall entwickelt.

„Kommt ein Detektiv in eine Action Bar, fragt der Ober…“ Ach, lassen wir das. Auch wenn sich bei dem Projektnamen genügend Witze anbieten würden, ist der Grund für das Projekt weniger amüsant. Mit Honeycomb (Android 3.x) hat Google die ActionBar als neues Navigationskonzept für Tablets etabliert und mit Ice Cream Sandwich auch auf Mobiltelefone gebracht. Leider hat sich Google nicht sonderlich um die Abwärtskompatibilität der ActionBar gekümmert, sodass allen Versionen vor Honeycomb die Navigation per ActionBar verwehrt bleibt. Auch die Supportbibliothek bietet nur grundlegende Abwärtskompatibilität für einige Komponenten, aber eben nicht für alle. Aufgrund dieses Missstands hat Jake Wharton – neben anderen Kompatibilitätsframeworks – das Projekt ActionBarSherlock ins Leben gerufen. ActionBarSherlock (ABS) ermöglicht die Nutzung des ActionBar-API auch unter älteren Android-Versionen und bietet somit die Möglichkeit, einheitliche Apps für die aktuell zu berücksichtigenden Android-Generationen zu entwickeln. Im diesem Artikel sollen die Vorteile sowie Besonderheiten bei der Entwicklung mit ABS anhand einer Beispielapplikation veranschaulicht werden. Das ActionBar-Pattern als solches wurde bereits in Ausgabe 1.2012 näher beleuchtet und wird im Folgenden nur noch kurz aufgegriffen.

Mehr zum Thema

Mehr zum Thema ActionBar lesen Sie im Android360 Magazin 1.2012 mit einem Artikel von Christian Meder.

Das ActionBar-Pattern

Mit der Einführung der ActionBar wurde der Grundstein für eine einheitliche und konsistente Navigation in Android-Anwendungen gelegt. Anwender können dabei die erlernten Benutzungsmuster über verschiedene Apps hinweg wiederverwenden und über die ActionBar auf die wichtigsten kontextabhängigen Aktionen schnell und direkt zugreifen. Entwickler profitieren von der Möglichkeit, ein ständig sichtbares und dabei die Anwendung identifizierendes Icon platzieren zu können. Darüber hinaus bieten Overflow-Menüs, Spinner und Navigations-Tabs als Elemente der ActionBar vielfältige Möglichkeiten, die eigene Anwendung dem aktuellen Android-Design entsprechend umzusetzen.

Durch ABS kommt man in den Genuss, diese Vorteile auch in Versionen vor Honeycomb einsetzen zu können. ABS unterstützt in der aktuell verfügbaren Version 4.1.0 die API-Level 7 bis 15 und ist unter der Apache-Lizenz frei verfügbar. Die Bibliothek erkennt automatisch, ob die ausführende Plattform die ActionBar nativ unterstützt. Ist dies nicht der Fall, wird die ABS-eigene Implementierung verwendet. Diese bietet alle Features des Originals und erlaubt den Wissenstransfer durch ein vollständig kompatibles API. So könnte bei der Entwicklung fast vergessen werden, dass nicht die richtige ActionBar genutzt, sondern auf ABS zurückgegriffen wird. Bis aber dieser Punkt erreicht ist, müssen zuerst die einzelnen Puzzleteile zu einer funktionsfähigen Installation zusammengeführt werden. Damit nicht zu viel Detektivarbeit notwendig ist, wird darauf detailliert im nächsten Abschnitt eingegangen.

Watson, ich kombiniere

Das Setup zur Nutzung von ABS beschränkt sich leider nicht nur auf den Download einer Bibliothek, sondern ist mit einigen Fallstricken versehen. Zuerst muss das Projektarchiv heruntergeladen werden [5] – aktuell ist die Version 4.1.0 verfügbar. Nach dem Entpacken des Archivs muss das ABS-Projekt in Eclipse als Android-Library-Projekt importiert werden. Eine Möglichkeit ist der Import im Package Explorer über die rechte Maustaste und die Menüs
IMPORT | ANDROID | EXISTING ANDROID CODE INTO WORKSPACE
oder über den NEW-Wizard und den Punkt ANDROID | ANDROID PROJECT FROM EXISTING CODE.
Dabei ist zu berücksichtigen, dass man den Unterordner library aus dem entpackten Archivordner als ROOT DIRECTORY für den Import auswählt. Hat man alles richtig gemacht, ist das Ergebnis ein nicht-kompilierendes Projekt. Des Rätsels Lösung ist die Änderung des JAVA COMPILER COMPLIANCE LEVEL von Java Version 1.5 auf 1.6 (rechte Maustaste auf den Projektordner: PROPERTIES | JAVA COMPILER | ENABLE PROJECT SPECIFIC SETTINGS | COMPILER COMPLIANCE LEVEL | 1.6). Nun sollte das Projekt erfolgreich kompilieren. Falls nicht, kann ein PROJECT | CLEAN manchmal Wunder vollbringen.Unabhängig davon, ob ein vorhandenes Projekt auf ABS umgestellt oder eine Anwendung von Grund auf neu entwickelt werden soll, muss im nächsten Schritt eine Verbindung vom Anwendungs- zum ABS-Projekt hergestellt werden. Da es sich bei ABS um ein Android-Library-Projekt handelt, muss dieses gesondert als Projektreferenz in den Einstellungen des Anwendungsprojekts über den ADD-Button hinzugefügt werden (PROPERTIES | ANDROID | LIBRARY). Damit sich beide Projekte vertragen, muss ebenfalls sichergestellt werden, dass sie mit derselben Android-Version kompilieren (PROPERTIES | ANDROID | PROJECT BUILD TARGET). Hier ist wiederum zu beachten, dass als Target bei Nutzung des aktuellen ABS-Release nur API-Level 14 oder 15 in Frage kommen. Die Konfiguration ist in Abbildung 1 dargestellt. Die Abwärtskompatibilität der Anwendung wird über den Manifest-Eintrag android:minSdkVersion im uses-sdk-Element erreicht (Listing 2). Die unterste Grenze ist hier aktuell API-Level 7, wobei auch auf die Abwärtskompatibilität anderer im Projekt genutzter APIs geachtet werden muss. Damit ist das Anwendungsprojekt präpariert (Abb. 2), und wir können zur Action übergehen.

Abb. 1: Konfiguration des Anwendungsprojektes

Abb. 2: Fertige Projektstruktur

[ header = Ab in die Action Bar ]

Ab in die Action Bar

Nach vollendeter Arbeit hat sich Sherlock nun eine Erfrischung verdient. Um auch eine angemessene Location dafür zu finden, nutzt er die „Bar Finder“-App (Abb. 3).

Abb. 3: Die Beispiel-App „Bar Finder“

Anhand dieser wird die Entwicklung mit ABS im Folgenden exemplarisch beschrieben. Die Nutzung von ABS bringt einige Besonderheiten mit sich. Die auffälligsten Änderungen sind die eigenen Basisklassen für Activities und Fragments, von denen geerbt werden muss. ABS bietet dazu folgende Klassen:

  • SherlockActivity
  • SherlockListActivity
  • SherlockExpandableListActivity
  • SherlockPreferenceActivity
  • SherlockFragment
  • SherlockFragmentActivity
  • SherlockDialogFragment
  • SherlockListFragment

Diese Klassen erweitern die Android-eigenen Basisklassen um die ABS-spezifischen Funktionalitäten und die entsprechenden Methoden. Die Grundfunktionalität bleibt dabei erhalten. Die Anwendung Bar Finder listet in der Haupt-Activity die nächstgelegenen Bars nach Entfernung sortiert auf. Dafür bietet sich die im Android-Framework enthaltene ListActivity an. Im ABS-Kontext nutzt man nun stattdessen die com.actionbarsherlock.app.SherlockListActivity (Listing 1).

package info.collide.android.barsearch;
import [...];
import com.actionbarsherlock.app.SherlockListActivity;
import com.actionbarsherlock.app.ActionBar;
// extending from SherlockListActivity
public class MainActivity extends SherlockListActivity {
   [...]
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
      ActionBar actionBar = getSupportActionBar();
      [...]
   }
   [...]
}

Während man ohne ABS über die Activity unter Zuhilfenahme der Methode getActionBar() an die ActionBar-Instanz gelangt, geschieht dies bei ABS über die Methode getSupportActionBar(). Zu beachten ist hier auch, dass die zurückgegebene Instanz den gleichen Namen und ein identisches API aufweist, die Implementierung der ActionBar jedoch eine andere ist. Somit zeigt der Import entsprechend auf die Klasse com.actionbarsherlock.app.ActionBar (Listing 1). Die Referenz auf die ActionBar bietet vollen Zugriff auf ihre Funktionen. So lassen sich beispielsweise der Titel (setTitle()), ein spezielles Icon (setIcon()) oder der Navigationsmodus (setNavigationMode()) der ActionBar setzen – eben genauso wie bei der normalen ActionBar. Standardmäßig wird in der ActionBar das Application- oder auch Launcher-Icon angezeigt. Dieses Verhalten lässt sich über die oben genannten Methoden verändern. Alternativ kann man das ActionBar-Icon auch über ein icon-Attribut der betreffenden Activity im AndroidManifest festlegen. In Listing 2 wird in der DetailActivity ein Pin-Icon gesetzt. Das AndroidManifest (Listing 2) der „Bar Finder“-Anwendung enthält eine weitere ABS-spezifische Besonderheit. Activities, die eine ABS ActionBar nutzen, müssen ein ABS-Theme verwenden. Dabei stehen verschiedene Themes zur Verfügung:

  • Theme.Sherlock
  • Theme.Sherlock.Light
  • Theme.Sherlock.Light.DarkActionBar

Diese lassen sich, wie beim ActionBar-Icon, entweder global für die gesamte Applikation setzen oder entsprechend in der Definition der jeweiligen Activity überschreiben. So wird in Listing 2 für die DetailActivity das globale Theme ersetzt.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="info.collide.android.barsearch" android:versionCode="1"
   android:versionName="1.0" >
   <uses-sdk
       android:minSdkVersion="7"
       android:targetSdkVersion="15" />
   [...]
   <application
     <!-- default application launcher icon - also used for the action bar -->
     android:icon="@drawable/ic_launcher"
     android:label="@string/app_name"
     <!-- sets default ABS theme for all activities -->
     android:theme="@style/Theme.Sherlock.Light.DarkActionBar" >
     [...]
     <activity android:name=".MainActivity" > [...] </activity>
     <activity android:name=".DetailsActivity"
      <!-- overrides default icon -->
      android:icon="@drawable/pin"
      <!-- overrides default theme -->
      android:theme="@style/Theme.Sherlock.Light.DarkActionBar.ForceOverflow" >
     </activity>
   </application>
</manifest>


[ header = Vorsicht mit dem Sherlock ]

Vorsicht mit dem Sherlock

Das bisher Beschriebene reicht schon aus, um in den Genuss der abwärtskompatiblen ActionBar zu kommen. Möchte man zusätzlich erweiterte Funktionalitäten der ActionBar nutzen, ist weitere Vorsicht geboten. Die DetailsActivity (Abb. 4) zeigt die Verwendung der ActionBar als Navigationsinstrument (Pin-Icon als Home-Button) und den erleichterten Zugriff auf wichtige Aktionen mithilfe von kontextabhängigen Menüelementen (z. B. Bewerten der aktuell angezeigten Bar).

Abb. 4: DetailsActivity mit gefüllter ActionBar

Wie bereits angesprochen: ABS kapselt die Funktionalitäten der ActionBar in einer eigenen, abwärtskompatiblen Implementierung. Diese kommt zum Einsatz, wenn keine native ActionBar verfügbar ist. Die Referenz erhält man über die ABS-spezifischen Activities, bei denen es zusätzliche Regeln zu beachten gilt. Soll ein Menü zur ActionBar hinzugefügt werden, so lässt sich das Menü entweder im Java-Code oder in XML definieren. Beide Ansätze haben die Gemeinsamkeit, dass das Menü über die Methode onCreateOptionsMenu() in der Activity gesetzt wird. Hierbei ist besonders bei der Migration einer bestehenden Anwendung hin zu ABS zu beachten, dass diese Methode nicht mehr in ihrer ursprünglichen Form zur Verfügung steht. Der Grund dafür ist, dass die Methode onCreateOptionsMenu() in den ABS-Activities final überschrieben wird und somit nicht in den erbenden Klassen noch einmal überschrieben werden kann. Damit soll die Verwendung dieser Methode verhindert und der Einsatz der ABS-eigenen Implementierung erzwungen werden. Der Unterschied in den beiden Methoden liegt im Typ des Parameters. Listing 3 zeigt die in diesem Fall zu nutzende Variante, die die angepasste Version der Menu-Klasse aus dem ABS-Package verwendet. Hier ist zusätzlich zu beachten, dass ein in XML definiertes Menü über einen spezifischen MenuInflater erzeugt wird, der über die Methode getSupportMenuInflater() aufzurufen ist.

Analog dazu verhält es sich mit der Methode onOptionsItemSelected(). Hier muss ebenfalls die ABS-spezifische Implementierung überschrieben werden, die als Parameter eine angepasste Version der MenuItem-Klasse übergibt. Die Nutzung dieser Klasse ist im Weiteren identisch zum Original.

package info.collide.android.barsearch;
import [...];
import com.actionbarsherlock.app.SherlockMapActivity;
// extending from SherlockMapActivity provided by the map plugin
public class DetailsActivity extends SherlockMapActivity {
   [...]
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      [...]
      getSupportActionBar().setHomeButtonEnabled(true);
      getSupportActionBar().setDisplayHomeAsUpEnabled(true);
      [...]
   }
   [...]
   // overriding from SherlockMapActivity
   @Override
   public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
      getSupportMenuInflater().inflate(R.menu.details, menu);
      return super.onCreateOptionsMenu(menu);
   	}
   // overriding from SherlockMapActivity
   @Override
   	public boolean onOptionsItemSelected(com.actionbarsherlock.view.MenuItem
         item) {
      if (item.getItemId() == android.R.id.home) {
         // just go back, like pressing the back button
         onBackPressed();
      }
      return super.onOptionsItemSelected(item);
   }
}


Die in Abbildung 4 dargestellte ActionBar enthält einen Overflow-Button. Das hierüber erreichbare Menü sammelt Aktionen, die aufgrund der je nach Gerät und Displayorientierung potenziell beschränkten Darstellungsfläche nicht mehr angezeigt werden können. Der Overflow-Button ist nur sichtbar, wenn das Gerät keinen Hardware-Menü-Button hat, über den auf das Overflow-Menü zugegriffen werden kann. Möchte man aus Konsistenzgründen auf diesen nicht verzichten, so kann man das Anzeigen des Overflow-Buttons erzwingen. Dies wird durch die Verwendung des Themes Theme.Sherlock.Light.DarkActionBar.ForceOverflow, wie bei der DetailsActivity im AndroidManifest (Listing 2) gezeigt, erreicht. Leider lässt sich dieser Zwang nur auf die Android-Versionen 2.x und 3.x ausüben, nicht jedoch auf Version 4.x.

Sherlocks Kartentrick

Abbildung 4 zeigt die beste Bar in der Gegend, die Sherlock über die „Bar Finder“-App finden konnte. Um auch zielgerichtet zur Bar zu gelangen, stellt die DetailsActivity neben Kurzbeschreibung und Foto auch einen Kartenausschnitt zur Verfügung. Zu diesem Zweck muss die entsprechende Activity von der MapActivity des Android-Frameworks erben. Im ABS-Kontext leitet man aber von den ABS-spezifischen Klassen (siehe oben) ab, wobei keine der MapActivity entsprechende Klasse angeboten wird. Hierzu bedient sich Sherlock eines simplen Tricks: Es existiert ein Plug-in [6], das genau diese Lücke schließt und in Form einer Bibliothek ins Projekt eingebunden werden muss (Abb. 2). Es erweitert das Framework um die Klasse SherlockMapActivity. Voraussetzung ist natürlich, dass das Projekt gegen die Google APIs, einschließlich Google Maps, kompiliert. Listing 3 zeigt die Verwendung dieser Klasse für die DetailsActivity.

Leider funktioniert dieser Trick nur im Falle von Activities. Sollen Fragments zum Einsatz kommen, muss man noch tiefer in die Trickkiste greifen. Der Grund dafür ist, dass Google leider noch keine einfache Möglichkeit vorgesehen hat, eine MapView in Fragments verwenden zu können. Abhilfe schafft hier das Ersetzen der Google Supportbibliothek durch eine angepasste Version. In dieser erbt FragmentActivity von der Klasse MapActivity. Das wiederum bedeutet, dass alle ABS-Fragments von MapActivity erben und somit eine MapView darstellen können. Der Nachteil dieser Lösung ist, dass auch solche Fragments von MapActivity erben, die eigentlich gar keine Karte darstellen sollen. Das könnte sich eventuell auf die Performance der Anwendung auswirken, sodass dieser Ansatz wohl bedacht eingesetzt werden sollte.

Fazit

Die ActionBar ist mittlerweile fester Bestandteil (fast) jeder aktuellen Google-Android-Anwendung und hat sich auch darüber hinaus etabliert. Dieser Artikel zeigt auf, welche Wichtigkeit ActionBarSherlock im Rahmen generationsübergreifender Anwendungsentwicklung zukommt. Nicht zuletzt nutzt Google selbst ABS für eigene Anwendungen, wie man beispielsweise in den kürzlich veröffentlichten Quellen der Google-I/O-2012-App begutachten kann. In jedem Fall ist die Verwendung von ABS eine gute Investition in die Zukunft. Nach Rücksprache mit Jake Wharton beginnt die Arbeit an der nächsten Version mit Unterstützung von Android 4.1 (Jelly Bean) in Kürze und könnte bei Erscheinen dieses Artikels bereits zur Verfügung stehen. Mithilfe dieses Artikels hat der Leser die wichtigsten Grundlagen für die Verwendung von ABS erlernt, sodass der Verwendung keine langwierige Detektivarbeit vorangehen muss.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -