Styles und Themes: Unterschied zwischen den Versionen

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen
K (Themes)
K
 
(Eine dazwischenliegende Version von einem anderen Benutzer wird nicht angezeigt)
Zeile 8: Zeile 8:
  
 
Eine einfache xml könnte dann z.B. so aussehen:
 
Eine einfache xml könnte dann z.B. so aussehen:
<code=xml>
+
<syntaxhighlight lang="java">
 
<resources>
 
<resources>
 
     <style name="NameDesStyles">
 
     <style name="NameDesStyles">
Zeile 14: Zeile 14:
 
     </style>
 
     </style>
 
</resources>
 
</resources>
</code=xml>
+
</syntaxhighlight>
  
 
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:
 
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>
+
<syntaxhighlight lang="java">
 
<style name="NameDesStyles">
 
<style name="NameDesStyles">
 
     <item name="android:background">#FF0000</item>
 
     <item name="android:background">#FF0000</item>
 
</style>
 
</style>
</code=xml>
+
</syntaxhighlight>
  
 
==Zuweisung==
 
==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:
 
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>
+
<syntaxhighlight lang="java">
 
<TextView  
 
<TextView  
 
     style="@style/NameDesStyles"
 
     style="@style/NameDesStyles"
Zeile 32: Zeile 32:
 
     android:layout_height="wrap_content"
 
     android:layout_height="wrap_content"
 
     android:text="Foo Bar" />
 
     android:text="Foo Bar" />
</code=xml>
+
</syntaxhighlight>
 
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.
 
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==
 
==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:
 
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>
+
<syntaxhighlight lang="java">
 
<style name="Eingabe">
 
<style name="Eingabe">
 
     <item name="android:layout_width">match_parent</item>
 
     <item name="android:layout_width">match_parent</item>
Zeile 49: Zeile 49:
 
     <item name="android:background">#CCCCCC</item>
 
     <item name="android:background">#CCCCCC</item>
 
</style>
 
</style>
</code=xml>
+
</syntaxhighlight>
 
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.  
 
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.  
  
Zeile 57: Zeile 57:
 
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.
 
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>
+
<syntaxhighlight lang="java">
 
<style name="Eingabe">
 
<style name="Eingabe">
 
     <item name="android:layout_width">match_parent</item>
 
     <item name="android:layout_width">match_parent</item>
Zeile 67: Zeile 67:
 
     <item name="android:background">#CCCCCC</item>
 
     <item name="android:background">#CCCCCC</item>
 
</style>
 
</style>
</code=xml>
+
</syntaxhighlight>
  
 
===Vererbung: Punktnotation===
 
===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'':
 
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>
+
<syntaxhighlight lang="java">
 
<style name="Eingabe">
 
<style name="Eingabe">
 
     <item name="android:layout_width">match_parent</item>
 
     <item name="android:layout_width">match_parent</item>
Zeile 82: Zeile 82:
 
     <item name="android:background">#CCCCCC</item>
 
     <item name="android:background">#CCCCCC</item>
 
</style>
 
</style>
</code=xml>
+
</syntaxhighlight>
  
 
Auch von diesem Stil (Eingabe.Gesperrt) kann dann wieder geerbt werden. Eine weitere Vererbung könnte dann z.B. so aussehen: ''Eingabe.Gesperrt.FooBar''.
 
Auch von diesem Stil (Eingabe.Gesperrt) kann dann wieder geerbt werden. Eine weitere Vererbung könnte dann z.B. so aussehen: ''Eingabe.Gesperrt.FooBar''.
Zeile 91: Zeile 91:
  
 
'''values/styles.xml'''
 
'''values/styles.xml'''
<code=xml>
+
<syntaxhighlight lang="java">
 
<resources>
 
<resources>
 
     <style name="AppBaseTheme" parent="android:Theme.Light">
 
     <style name="AppBaseTheme" parent="android:Theme.Light">
Zeile 103: Zeile 103:
  
 
</resources>
 
</resources>
</code=xml>
+
</syntaxhighlight>
  
  
 
'''values-v11/styles.xml'''
 
'''values-v11/styles.xml'''
<code=xml>
+
<syntaxhighlight lang="java">
 
<resources>
 
<resources>
  
Zeile 116: Zeile 116:
 
</resources>
 
</resources>
  
</code=xml>
+
</syntaxhighlight>
  
 
Die App selber nutzt dann den Style '''AppTheme''' als eigentliches Theme und die Plattform entscheidet dann, welche Definition des Styles '''AppBaseTheme''' greift.
 
Die App selber nutzt dann den Style '''AppTheme''' als eigentliches Theme und die Plattform entscheidet dann, welche Definition des Styles '''AppBaseTheme''' greift.
Zeile 123: Zeile 123:
  
 
=Eigenschaft von Theme übernehmen=
 
=Eigenschaft von Theme übernehmen=
Auch hier zunächst ein Beispiel: wir haben einen View mit transparentem Hintergrund und schwarzer Schrift. Würden wir nun ein Theme einstellen mit schwarzem Hintergrund, 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]'''.  
+
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 wollen wir das mal auf unseren obigen Style anwenden und dieser schaut dann wie folgt aus:
+
Nun wenden wir dies auf das obigen Style an und das ganze schaut dann wie folgt aus:
  
<code=xml>
+
<syntaxhighlight lang="java">
 
<style name="NameDesStyles">
 
<style name="NameDesStyles">
 
     <item name="android:background">?android:background</item>
 
     <item name="android:background">?android:background</item>
 
</style>
 
</style>
</code=xml>
+
</syntaxhighlight>
  
 
=Video-Tutorial=
 
=Video-Tutorial=

Aktuelle Version vom 19. September 2019, 12:28 Uhr

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:

<resources>
    <style name="NameDesStyles">
        <!-- Hier werden die Attribute angelegt -->
    </style>
</resources>

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:

<style name="NameDesStyles">
    <item name="android:background">#FF0000</item>
</style>

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:

<TextView 
    style="@style/NameDesStyles"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Foo Bar" />

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:

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

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.

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

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:

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

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

<resources>
    <style name="AppBaseTheme" parent="android:Theme.Light">
         <!-- Für alle Geräte unter Api-11 -->
    </style>

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
         <!-- Alle API-Unabhängigen Eigenschaften -->
    </style>

</resources>


values-v11/styles.xml

<resources>

    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
        <!-- API 11 theme anpassungen -->
    </style>

</resources>

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:

<style name="NameDesStyles">
    <item name="android:background">?android:background</item>
</style>

Video-Tutorial

Zu diesem Thema habe ich auch ein Videotutorial gemacht. Dieses findet Ihr hier:Android - Android XML Style + Theme