Styles und Themes
Inhaltsverzeichnis
Styles
Diese ermöglichen es uns beliebig viele Attribute zusammenzufassen. Wird ein solcher Style einem View zugewiesen, so übernimmt dieser die angegebenen Werte. Um Redundanzen zu vermeiden können Styles aufeinander aufbauen und Werte hinzufügen oder überschreiben.
Somit helfen uns Styles den Code übersichtlich zu halten und nehmen uns Wartungsaufwand ab. Da ein Style mehreren Elementen zugewiesen werden kann, können wir an einer zentralen Stelle direkten Einfluss auf betroffene Elemente ausüben.
Das Grundgerüst
Styles werden in einer XML-Datei angelegt. Der Name der Datei kann dabei beliebig gewählt werden, oft wird diese aber einfach styles.xml genannt. Diese XML-Datei muss sich im Resourcen-Ordner values befinden.
Eine einfache xml könnte dann z.B. so aussehen: <code=xml> <resources>
<style name="NameDesStyles"> </style>
</resources> </code=xml>
Der style-Tag kann beliebg viele item-Tags aufnehmen. Die items besitzen ein Attribut name welches das Zielattribut definiert. Der zugehörige Wert wird dann als Inhalt in den Tag geschrieben. Hier ein Beispiel wie man einen roten Hintergrund definieren kann:
<code=xml> <style name="NameDesStyles">
<item name="android:background">#FF0000</item>
</style> </code=xml>
Zuweisung
Ausgehend von dem obigen Beispiel wollen wir diesen Style nun einem TextView zuweisen. Dazu nutzen wir das Attribut style und geben dort folgendes an: @style/NameDesStyles. Nachfolgend ist ein Auszug einer möglichen Layout-Datei zu sehen, die diesen Style verwendet: <code=xml> <TextView
style="@style/NameDesStyles" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Foo Bar" />
</code=xml> Im Layout selber haben wir dann letztendlich noch die Möglichkeit die Werte des angegebenen Styles zu überschreiben. Wenn wir also folgendes Attribut setzen würden: android:background='#0000FF', so wäre der Hintergrund blau und nicht rot.
Vererbung
Dies wollen wir an einem Beispiel verdeutlichen. Angenommen wir haben einen Style welcher das Aussehen eines Eingabefeldes definiert. Zusätzlich brauchen wir ein definiertes Aussehen für das selbe Eingabefeld wenn es gesperrt ist - in diesem Fall soll einfach der Hintergrund Grau sein aber alles andere bleibt gleich. Ohne Vererbung müssten man dies mit zwei Style-Definitionen lösen: <code=xml> <style name="Eingabe">
<item name="android:layout_width">match_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:background">#00FF00</item>
</style>
<style name="EingabeGesperrt">
<item name="android:layout_width">match_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:background">#CCCCCC</item>
</style> </code=xml> Schon in diesem kurzen Beispiel haben wir einiges an Redundanzen. Zusätzlich wird so ein erhöhter Pflegeaufwand + eine potentielle Fehlerquelle geschaffen - denn Änderungen die den Style Eingabe betreffen, müssen auch im Style EingabeGesperrt nachgezogen werden.
Deswegen gibt es eine elegantere Methode wie wir dieses Problem lösen können. Nämlich mithilfe von Vererbung. Dazu gibt es zwei Techniken wie man die Vererbung bewerkstelligen kann.
Vererbung: Parent
Die erste Möglichkeit wie man Vererbung angehen kann ist über das Attribut parent des style-Tags. Dort gibt man einfach den zu erbenden Style an und die Werte werden entsprechend übernommen. Als Angabe ist sowohl nur der Name des Stils (Eingabe) als auch die "Resourcenschreibweise" (@style/Eingabe) gültig.
<code=xml> <style name="Eingabe">
<item name="android:layout_width">match_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:background">#00FF00</item>
</style>
<style name="EingabeGesperrt" parent="Eingabe">
<item name="android:background">#CCCCCC</item>
</style> </code=xml>
Vererbung: Punktnotation
Die zweite Möglichkeit wäre dann die Punktnotation. Dabei wird nicht das parent-Attribut genutzt, sondern eine spezielle Form der Namensgebung. Zuerst wird der Name des zu erbenden Stils angegeben, danach folgt ein Punkt. Als nächstes schreibt man den eigentlichen Namen des Stils direkt dahinter. In unserem Fall also Eingabe.Gesperrt:
<code=xml> <style name="Eingabe">
<item name="android:layout_width">match_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:background">#00FF00</item>
</style>
<style name="Eingabe.Gesperrt">
<item name="android:background">#CCCCCC</item>
</style> </code=xml>
Auch von diesem Stil (Eingabe.Gesperrt) kann dann wieder geerbt werden. Eine weitere Vererbung könnte dann z.B. so aussehen: Eingabe.Gesperrt.FooBar.
Themes
Über das Theme kann die App den Bedürfnissen/Vorgaben angepasst werden. Ein Theme ist letztendlich nichts anderes wie ein Style der ganz vielen Eigenschaften vorgibt. Um ein eigenes Theme zu entwickeln bietet es sich an von einem bestehenden zu erben und anzupassen. Dabei sollte aber beachtet werden, dass der Style auch auf jeder Zielplattform verfügbar ist. Um verschiedene Android-Versionen zu unterstützen bietet sich folgende Struktur an:
values/styles.xml
<code=xml>
<resources>
<style name="AppBaseTheme" parent="android:Theme.Light"> </style>
<style name="AppTheme" parent="AppBaseTheme"> </style>
</resources> </code=xml>
values-v11/styles.xml
<code=xml>
<resources>
<style name="AppBaseTheme" parent="android:Theme.Holo.Light"> </style>
</resources>
</code=xml>
Die App selber nutzt dann den Style AppTheme als eigentliches Theme und die Plattform entscheidet dann, welche Definition des Styles AppBaseTheme greift.
Alternativ bieten Bibliotheken wie ActionbarSherlock oder das support-package-v7 Themes an, die Rückwärtskompatibel sind. Dann benötigt man keine Unterscheidung der Versionen.
Eigenschaft von Theme übernehmen
Auch hier zunächst ein Beispiel: wir haben einen View mit transparentem Hintergrund und schwarzer Schrift. Würden man nun ein Theme einstellen welches einen schwarzem Hintergrund definiert, dann könnte man den Text nicht mehr lesen. Aus diesem Grund ist es möglich Werte des Styles an Werte des Themes zu binden. Da ein Theme mit schwarzem Hintergrund keine schwarze Schriftfarbe verwenden würde, sollten wir die Textfarbe des Themes für unseren Style übernehmen. Dazu müssen wir einfach nur das gewünschte Attribut angeben und nutzen dazu folgendes Schema: ?android:attr/[Name].
Nun wenden wir dies auf das obigen Style an und das ganze schaut dann wie folgt aus:
<code=xml> <style name="NameDesStyles">
<item name="android:background">?android:background</item>
</style> </code=xml>
Video-Tutorial
Zu diesem Thema habe ich auch ein Videotutorial gemacht. Dieses findet Ihr hier:Android - Android XML Style + Theme