Fragmentierung auf der Android-Plattform

Bildschirme groß und klein

Nachdem es uns nun möglich ist, grafische Elemente in konstanter Größe und Qualität über verschiedene Auflösungsbereiche darzustellen, stellt sich die Frage, wie wir das Layout ebenso souverän über verschiedene Bildschirmgrößen steuern können. Wäre man für Version 1.5 wie bei der iOS-Entwicklung noch mit einem AbsoluteLayout davongekommen, so wird einem spätestens seit 1.6 davon durch ein dezentes @deprecated abgeraten.

Für den aufgeklärten Entwickler war AbsoluteLayout allerdings noch nie eine Option. Jener bevorzugt nämlich dynamische Layouts, die v. a. auf den View Groups LinearLayout oder RelativeLayout basieren. Damit kann auch schon der Wechsel vom Portrait- in den Landscape-Modus hinreichend glanzvoll bewältigt werden, der abstrakt gesehen ja auch einen Bildschirmwechsel darstellt.

Aber auch das flexibelste Linear- oder RelativeLayout hat seine Grenzen und sieht irgendwann nicht mehr schön aus. Auf kleinen Bildschirmen kann es sein, dass nicht alle Informationen Platz finden, auf großen dagegen hätten wir noch Raum für Zusatzinformationen.

Auch hier kommt uns das System mit geeigneten Mitteln zu Hilfe. Analog zu den oben erwähnten Auflösungsklassen werden auch die Bildschirmgrößen in diskrete Stufen unterteilt: small, medium, large und xlarge. Die konkrete Unterteilung ist in Abb. 5 dargestellt.

Abb. 5: Bildschirmgrößen-Klassen der Android-Plattform

Für jede dieser Größenklassen können nun unterschiedliche Layouts definiert werden. Dazu muss man lediglich Versionen seines Layout-XML-Files in den Ordnern res/layout-[small|medium|large|xlarge] ablegen. Und auch hier bietet das System einen einheitlichen Zugriff über einen gemeinsamen Resource Identifier (Bsp.: R.layout.yourlayoutxml) und auch hier wird vom nicht weiter qualifizierten Verzeichnis („res/layout“) angenommen, dass es für mittlere Größenverhältnisse steht.

Für den vorhin erwähnten Wechsel der Bildschirmorientierung können übrigens auch spezielle Layouts bereitgestellt werden. Neben der Angabe der Bildschirmklasse muss hier noch ein Qualifizierer der Orientierung port (portrait) bzw. land (landscape) hinzugefügt werden. layout-small-land ist beispielsweise für Layouts für kleine Bildschirme in Portrait-Orientierung gedacht.

Schauen wir uns zum besseren Verständnis ein kleines Beispiel an: In der zentralen ListView einer Activity sollen News-Feed-Einträge dargestellt werden (Bild, Überschrift, Beschreibung, Autor, Datum). Das von uns gewählte klassische Layout (Bild links, rechts davon untereinander: Überschrift, Beschreibung, Datum und Autor) kann problemlos auf mittleren und großen Bildschirmklassen dargestellt werden. Auch auf kleinen Bildschirmen in Landscape-Orientierung sieht es hinreichend gut aus. Auf großen Tabletscreens bleibt allerdings zu viel Platz übrig. Lösung: für unser list_item.xml brauchen wir angepasste Lösungen in den Ressourcenordnern:

  • res/layout/list_item.xml
  • res/layout-small-port/list_item.xml
  • res/layout-xlarge/list_item.xml

Für den Fall, dass wir es mit der Größenklasse small in Portrait-Orientierung zu tun haben, soll das /res/layout-small-port/item.xml-Layoutfile verwendet werden. Aufgrund der eingeschränkten Bildschirmbreite werden wir hier auf die Darstellung des Icons verzichten. Auf Tablets (>=10″) haben wir genug Platz, um zusätzlich den vollständigen Abstract darzustellen – dafür ist das res/layout-xlarge/list_item.xml-Layout definiert. Für alle anderen Fälle, die durch obige Layoutdefinitionen nicht abgedeckt werden, wird res/layout/list_item.xml verwendet, d. h. für alle medium- oder large-Bildschirme sowie small-Bildschirme in Landscape-Orientierung.

In der Implementierung des Adapters für unsere ListView können wir nun einheitlich R.layout.list_item als Layout referenzieren und die einzelnen View-Elemente befüllen. Doch Vorsicht! Da sich unsere Version von list_item je nach Bildschirm unterscheiden kann, müssen wir dies im Code berücksichtigen. Je nach Layout, das zur Anwendung kommt, kann es sein, dass wir z. B. nicht auf die ImageView für die Icon-Darstellung zugreifen können oder andersrum uns eine zusätzliche TextView für die Darstellung des Abstract-Textes zur Verfügung steht. In der Regel überprüft man hier den Aufruf von findViewById(), um an die jeweilige Layoutkomponente zu kommen, auf null und passt den Programmfluss entsprechend an.

Die Unterspezifizierung der Applikationsressourcen ist übrigens nicht nur über die Qualifizierung der Auflösung, Bildschirmgröße und Orientierung möglich. Android bietet eine Fülle von möglichen Unterscheidungskriterien. Für die ausführliche Dokumentation sei hier auf [1] verwiesen.

Konfigurationsmöglichkeiten

Mit den bisher beschriebenen Mitteln ist es möglich, die eigene Applikation fit für alle Geräteklassen zu machen, vom kleinen Kompakt-Androiden bis zum neuesten Tablet. Doch was tun, wenn es gar keinen Sinn macht, die Applikation auf Smartphones anzubieten oder ein Tablet-taugliches UI erst im Folgerelease nachgeschoben werden soll?

Im Android-Manifest können mittels der XML-Elemente <supports-screens> und <compatible-screens> die unterstützten Zielbildschirme definiert werden. Das Besondere dabei ist, dass diese Konfigurationen auch vom Marketplace berücksichtigt werden, sodass Besitzer/innen von ausgeschlossenen Geräteklassen erst gar nicht in die Versuchung kommen, die Applikation herunterzuladen. Mittels <supports-screens> können beispielsweise kleine und mittlere Bildschirmgrößen deaktiviert werden.

Deaktiviert man jedoch die großen und sehr großen Größen, heißt das nicht, dass die Applikation dafür nicht verfügbar ist. Es wird dafür lediglich der sog. Screen-Compatibility-Modus aktiviert. D. h. die Applikation wird für ein Smartphone normaler Größe gerendert und dann proportional hochskaliert, mit allen negativen Effekte, was die Darstellung betrifft.

Will man die Darstellung auf großen Bildschirmen jedoch strikt verbieten, bleibt einem nur die Verwendung des <compatible-screens>-Elements. Hier müssen explizit alle unterstützten Screen-Density-Kombinationen definiert werden. Für alle Geräte mit anderen nicht erwähnten Kombinationen wird die App nicht bereitgestellt.

Die explizite Definition der <compatible-screens> sollte der letzte Ausweg sein. Meistens reicht es aus, die jeweiligen Angaben mittels <supports-screens> zu hinterlegen.

Android 3.2 und später

Android wäre nicht Android, wenn es sich nicht permanent weiterentwickeln würde. Mit 3.2 wurde das Konzept der diskreten Bildschirmklassen wieder flexibilisiert. Anstelle von fixen Kategorisierungen wird hier mit Minimalbreiten und -höhen gearbeitet, welche entweder orientierungsabhängig oder -unabhängig definiert werden können. Letzteres ist sicherlich sinnvoller. Aktuell betrifft dies nur einen sehr kleinen Prozentsatz von Geräten, sodass das hier Gelernte noch eine Weile seine Gültigkeit behalten wird. Der Vollständigkeit halber sei es jedoch hier schon erwähnt.

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.