Freunde, den ganzen Freitag großartig. Wir möchten Ihnen eine Übersetzung eines Artikels mitteilen, der speziell für Studenten des Kurses
„Android-Entwickler. Fortgeschrittenenkurs .
“ Gute Lektüre.

So deklarieren Sie Text unter Android deklarativ.
Virginia Poltrack IllustrationTextView
in Android-Anwendungen bietet verschiedene Attribute zum Stylen von Text und verschiedene Möglichkeiten, sie anzuwenden. Diese Attribute können direkt im Layout festgelegt werden, einen Stil auf die Ansicht oder das Thema auf das Layout anwenden oder, wenn Sie möchten, textAppearance festlegen. Aber was davon sollte verwendet werden? Und was passiert, wenn Sie sie kombinieren?
Was und wann verwenden?In diesem Artikel werden verschiedene Ansätze zur deklarativen Stilisierung von Text beschrieben (dh wenn Sie Stile in einer XML-Datei definieren). Außerdem werden Umfang und Priorität der einzelnen Methoden erläutert.
tl; dr;
Sie
sollten den gesamten Beitrag lesen, aber hier ist eine Zusammenfassung.
Denken Sie an die Prioritätsreihenfolge verschiedener Stilmethoden. Wenn Sie versuchen, Text zu stilisieren und die erwarteten Ergebnisse nicht sehen, werden Ihre Änderungen höchstwahrscheinlich von etwas mit einer höheren Priorität in dieser Hierarchie überschrieben:
Hierarchie der TextstilmethodenIch würde das folgende Verfahren für das Styling vorschlagen:
textViewStyle
Sie einen beliebigen Anwendungsstil in textViewStyle
als Standardstil für Ihr Thema fest.- Installieren Sie den (kleinen) Satz von
TextAppearance
, den Ihre Anwendung verwendet (oder von MaterialComponent- Stilen verwendet / erbt), und verweisen Sie direkt aus Ihrer Ansicht darauf - Erstellen Sie einen
style
indem Sie Attribute TextAppearance
die von TextAppearance
nicht unterstützt werden (die selbst einen Ihrer TextAppearance
). - Führen Sie ein einzigartiges Styling direkt im Layout durch.
Zeigen Sie etwas Stil
Sie können die
TextView
Attribute direkt im Layout
TextView
, dieser Ansatz kann jedoch langwieriger und unsicherer sein. Stellen Sie sich vor, Sie versuchen auf diese Weise, die Farbe aller TextViews in der Anwendung zu aktualisieren. Wie bei allen anderen Ansichten können (und sollten!) Sie stattdessen Stile verwenden, um Konsistenz, Wiederverwendung und einfache Aktualisierung sicherzustellen. Zu diesem Zweck empfehle ich, Stile für Text zu erstellen, wenn Sie wahrscheinlich denselben Stil auf mehrere Ansichten anwenden möchten. Dies ist äußerst einfach und wird weitgehend vom Android-Ansichtssystem unterstützt.
Was passiert unter der Haube, wenn Sie die Ansicht stylen? Wenn Sie jemals Ihre benutzerdefinierte Ansicht geschrieben haben, haben Sie wahrscheinlich den Aufruf von
context.obtainStyledAttributes (AttributeSet, int [], int, int) gesehen . Somit übergibt das Ansichtssystem in Android die im Layout angegebenen Attribute an die Ansicht. Der
AttributeSet
Parameter kann tatsächlich als Zuordnung der XML-Parameter betrachtet werden, die Sie in Ihrem Layout angeben. Wenn das AttributeSet den Stil festlegt, wird der
Stil zuerst gelesen und dann werden die direkt in der Ansicht angegebenen Attribute darauf angewendet. Damit kommen wir zur ersten Prioritätsregel.
Ansicht → StilDirekt in der Ansicht definierte Attribute "überwiegen" immer und überschreiben die im Stil definierten Attribute. Beachten Sie, dass eine
Kombination aus Stil- und Ansichtsattributen angewendet wird. Durch das Definieren eines Attributs in der Ansicht, das auch im Stil angegeben ist,
wird nicht der gesamte Stil abgebrochen. Es sollte auch beachtet werden, dass es Ihrer Ansicht nach keine wirkliche Möglichkeit gibt, festzustellen, woher die Stilisierung kommt. Dies wird vom Ansichtssystem für Sie einmal in einem ähnlichen Anruf entschieden. Sie können nicht beide Optionen erhalten und auswählen.
Obwohl Stile äußerst nützlich sind, haben sie ihre Grenzen. Eine davon ist, dass Sie nur einen Stil auf die Ansicht anwenden können (im Gegensatz zu CSS, bei dem Sie mehrere Klassen anwenden können).
TextView
hat jedoch einen Trick: Es stellt das
TextAppearance
Attribut
TextAppearance
, das ähnlich wie der
style
funktioniert. Wenn Sie Text über
TextAppearance
, lassen Sie das
TextAppearance
für andere Stile frei, was praktisch aussieht. Schauen wir uns genauer an, was
TextAppearance
und wie es funktioniert.
Textauftritt
TextAppearance
nichts Magisches (zum Beispiel einen geheimen Modus zum Anwenden mehrerer Stile, über die Sie nichts wissen sollten !!!!).
TextView
erspart Ihnen unnötige Arbeit. Schauen wir uns den
TextView
Konstruktor an, um zu verstehen, was passiert.
TypedArray a = theme.obtainStyledAttributes(attrs, com.android.internal.R.styleable.TextViewAppearance, defStyleAttr, defStyleRes); TypedArray appearance = null; int ap = a.getResourceId(com.android.internal.R.styleable.TextViewAppearance_textAppearance, -1); a.recycle(); if (ap != -1) { appearance = theme.obtainStyledAttributes(ap, com.android.internal.R.styleable.TextAppearance); } if (appearance != null) { readTextAppearance(context, appearance, attributes, false); appearance.recycle(); }
Also, was ist hier los? Im Wesentlichen
TextView
die
TextView
zunächst, ob Sie
android:textAppearance
angegeben haben. In diesem
android:textAppearance
wird dieser Stil
android:textAppearance
und alle dort aufgeführten Eigenschaften werden
android:textAppearance
. Später lädt er alle Attribute aus der Ansicht (an die er sich erinnert, einschließlich des Stils) und wendet sie an. Wir kommen also zur Regel der zweiten Priorität:
Ansicht → Stil → TextdarstellungDa das Erscheinungsbild des Texts zuerst überprüft wird, werden alle Attribute, die entweder direkt in der Ansicht oder im Stil definiert sind, überschrieben.
Bei
TextAppearance
ist noch eine weitere
TextAppearance
zu beachten: Es unterstützt eine
Teilmenge der
TextView
, die
TextView
bietet. Um besser zu verstehen, was ich meine, gehen wir zurück zu dieser Zeile:
obtainStyledAttributes(ap, android.R.styleable.TextAppearance);
Wir haben uns die Version
receiveStyledAttributes
mit 4 Argumenten angesehen. Diese Version mit 2 Argumenten unterscheidet sich geringfügig davon. Sie betrachtet den angegebenen Stil (wie durch die erste Parameter-
id
) und filtert ihn nur nach den Attributen im Stil, die im zweiten Parameter, dem
attrs
Array,
attrs
. So definiert styleable
android.R.styleable.TextAppearance
den Umfang der
TextAppearance
. Wenn wir uns diese Definition ansehen,
TextAppearance
wir, dass
TextAppearance
viele,
aber nicht alle Attribute
unterstützt , die
TextView
unterstützt .
<attr name="textColor" /> <attr name="textSize" /> <attr name="textStyle" /> <attr name="typeface" /> <attr name="fontFamily" /> <attr name="textColorHighlight" /> <attr name="textColorHint" /> <attr name="textColorLink" /> <attr name="textAllCaps" format="boolean" /> <attr name="shadowColor" format="color" /> <attr name="shadowDx" format="float" /> <attr name="shadowDy" format="float" /> <attr name="shadowRadius" format="float" /> <attr name="elegantTextHeight" format="boolean" /> <attr name="letterSpacing" format="float" /> <attr name="fontFeatureSettings" format="string" />
Von TextAppearance
unterstützte Styling-AttributeHier sind einige
TextView
Attribute, die nicht in
TextAppearance
:
lineHeight[Multiplier|Extra]
,
lines
,
breakStrategy
und
breakStrategy
.
TextAppearance
funktioniert auf Zeichenebene und nicht auf
TextAppearance
, sodass Attribute, die sich auf das gesamte Layout auswirken, nicht unterstützt werden.
Daher ist
TextAppearance
sehr nützlich. Es ermöglicht uns, einen Stil zu definieren, der sich an den
TextAppearance
orientiert, und lässt den
style
für andere Zwecke frei. Es hat jedoch einen begrenzten Umfang und befindet sich am Ende der Prioritätskette. Vergessen Sie also nicht die Einschränkungen.
Angemessene Standardeinstellungen
Als wir uns angesehen haben, wie die Android-Ansicht Attribute auflöst (
context.obtainStyledAttributes
), haben wir es tatsächlich ein wenig vereinfacht. Sie ruft
theme.obtainStyledAttributes auf (unter Verwendung des aktuellen
Theme Context
'a). Beim Überprüfen des
Links wird die zuvor untersuchte Prioritätsreihenfolge angezeigt, und es werden zwei weitere Stellen angezeigt, nach denen er sucht, um Attribute aufzulösen: der Standardstil für die Ansicht und das Thema.
Bei der Bestimmung des Endwerts eines bestimmten Attributs kommen vier Eingabeparameter ins Spiel:
- Alle Attributwerte in diesem AttributeSet.
- Die im AttributeSet angegebene Stilressource (mit dem Namen "style").
- Der von defStyleAttr und defstyleres angegebene Standardstil
- Grundwerte in diesem Thread.
Styling Priority Order aus der ThemendokumentationWir werden auf die Themen zurückkommen, aber schauen wir uns zuerst die Standardstile an. Was ist dieser Standardstil? Um diese Frage zu beantworten, halte ich es für nützlich, das
TextView
Thema ein wenig zu verlassen und einen einfachen
Button
. Wenn Sie
<
Button
>
in Ihr Layout einfügen, sieht es ungefähr so aus.
StandardknopfWarum? Wenn Sie sich den Quellcode von
Button
ansehen, werden Sie feststellen, dass er eher dürftig ist:
public class Button extends TextView { public Button(Context context) { this(context, null); } public Button(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.buttonStyle); } public Button(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public Button(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public CharSequence getAccessibilityClassName() { return Button.class.getName(); } @Override public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) { if (getPointerIcon() == null && isClickable() && isEnabled()) { return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND); } return super.onResolvePointerIcon(event, pointerIndex); } }
Das ist alles! Hier ist die ganze Klasse (kein Kommentar). Sie können
es hier selbst überprüfen. Ich warte. Woher kommen also Hintergrund, Großbuchstaben, Welligkeit usw.? Möglicherweise haben Sie etwas verpasst, aber alles wird im Konstruktor mit zwei Argumenten definiert. Eine, die aufgerufen wird, wenn das Layout aus XML übernommen wird. Dies ist der letzte Parameter, der
defaultStyleAttr
in
com.android.internal.R.attr.buttonStyle
definiert. Dies ist der Standardstil, bei dem es sich im Wesentlichen um einen indirekten Referenzpunkt handelt, mit dem Sie den Standardstil angeben können. Es zeigt nicht direkt auf den Stil, sondern ermöglicht es Ihnen, auf einen der in Ihrem Thema angegebenen Stile zu verweisen, die beim Auflösen von Attributen überprüft werden. Und genau das tun alle Themen, von denen Sie normalerweise erben, um das Erscheinungsbild von Standard-Widgets zu erhalten. Wenn Sie sich beispielsweise das Thema Material ansehen, definiert es
@style/Widget.Material.Light.Button
, und dieser Stil bietet alle Attribute, die
theme.obtainStyledAttributes
wenn Sie nichts anderes angegeben haben.
Zurück zu
TextView
bietet es auch einen Standardstil:
textViewStyle
. Dies kann sehr praktisch sein, wenn Sie einige Stile auf jede Textansicht in Ihrer Anwendung anwenden möchten. Angenommen, Sie möchten den Standardzeilenabstand auf 1,2 festlegen. Sie können dies mit
style/TextAppearance
und versuchen, es während einer
style/TextAppearance
(oder vielleicht sogar mit einer eleganten benutzerdefinierten Regel in Lint) anzuwenden. Sie müssen jedoch wachsam sein und sicherstellen, dass Sie neue Teammitglieder einstellen , seien Sie vorsichtig beim Refactoring usw.
Ein besserer Ansatz wäre, Ihren eigenen Standardstil für alle
TextView
in der Anwendung anzugeben und das gewünschte Verhalten
TextView
. Sie können dies tun, indem Sie Ihren eigenen Stil für
textViewStyle
, der standardmäßig von der Plattform oder von
MaterialComponents/AppCompat
wird.
<style name="Theme.MyApp" parent="@style/Theme.MaterialComponents.Light"> ... <item name="android:textViewStyle">@style/Widget.MyApp.TextView</item></style> <style name="Widget.MyApp.TextView" parent="@android:style/Widget.Material.TextView"> <item name="android:textAppearance">@style/TextAppearance.MyApp.Body</item> <item name="android:lineSpacingMultiplier">@dimen/text_line_spacing</item> </style>
In diesem Sinne hat unsere Prioritätsregel die Form:
Ansicht -> Stil -> Standardstil -> TextdarstellungIm Rahmen der Auflösung der Attribute des Ansichtssystems wird dieser Slot nach den Stilen ausgefüllt (sodass standardmäßig alles im Stil durch den angewendeten Stil oder die Ansichtsattribute gelöscht wird), überschreibt jedoch weiterhin das Erscheinungsbild des Texts. Standardstile können sehr praktisch sein. Wenn Sie sich jemals dazu entschließen, eine eigene benutzerdefinierte Ansicht zu schreiben, können diese eine leistungsstarke Methode zum Implementieren des Standardverhaltens sein und das Anpassen vereinfachen.
Wenn Sie das Widget erben und keinen eigenen Standardstil angeben, müssen Sie den Standardstil der übergeordneten Klasse in den Konstruktoren verwenden (übergeben Sie nicht nur 0). Wenn Sie beispielsweise von
AppCompatTextView
erben und Ihren eigenen Konstruktor mit 2 Argumenten schreiben, müssen Sie
android.R.attr.textViewStyle defaultStyleAttr
(
wie hier ) übergeben, da Sie sonst das Verhalten der übergeordneten Klasse verlieren.
Themen
Wie bereits erwähnt, gibt es eine andere (ich verspreche es letzte) Möglichkeit, Styling-Informationen bereitzustellen. Ein anderer Ort
theme.obtainStyledAttributes
wird direkt in das Thema selbst schauen. Das heißt, wenn Sie Ihrem Thema ein
android:textColor
hinzufügen, z. B.
android:textColor
,
android:textColor
das Ansichtssystem es als letzten Ausweg aus. In der Regel ist es eine schlechte Idee, Themenattribute und Stilattribute zu mischen. Das heißt, was Sie direkt auf die Ansicht anwenden, sollte in der Regel niemals für das Thema festgelegt werden (und umgekehrt), aber es gibt einige seltene Ausnahmen.
Ein Beispiel wäre, wenn Sie versuchen, die Schriftart in der gesamten Anwendung zu ändern. Sie können eine der oben beschriebenen Methoden verwenden, aber das manuelle Anpassen der Stile / des Erscheinungsbilds des Texts überall ist eintönig und unsicher, und die Standardstile funktionieren nur auf Widget-Ebene. Unterklassen können dieses Verhalten überschreiben. Beispielsweise definieren Schaltflächen ihren eigenen
android:buttonStyle
, den Ihr
android:textViewStyle
nicht
android:textViewStyle
. Stattdessen können Sie die Schriftart in Ihrem Thema angeben:
<style name="Theme.MyApp" parent="@style/Theme.MaterialComponents.Light"> ... <item name="android:fontFamily">@font/space_mono</item> </style>
Jetzt nimmt jede Ansicht, die dieses Attribut unterstützt, es auf, wenn es nicht von etwas mit einer höheren Priorität überschrieben wird:
Ansicht → Stil → Standardstil → Thema → TextdarstellungDa dies wiederum Teil des Ansichtsstilsystems ist, überschreibt es alles, was in Textform bereitgestellt wird, wird jedoch durch spezifischere Attribute überschrieben.
Denken Sie an diese Priorität. In unserem Beispiel mit einer Schriftart für die gesamte Anwendung können Sie erwarten, dass die
Toolbar
diese Schriftart
TextView
, da sie den Titel enthält, bei dem es sich um eine
TextView
. Die Toolbar-Klasse selbst definiert jedoch einen Standardstil mit
titleTextAppearance
, der
android:fontFamily
definiert, und legt ihn direkt im
TextView
Header fest, wobei der Wert auf
TextView
überschrieben wird. Stile auf Themenebene können nützlich sein, lassen sich jedoch leicht überschreiben. Stellen Sie daher sicher, dass sie ordnungsgemäß angewendet werden.
Bonus: Ungelöste Probleme
Dieser gesamte Artikel widmete sich der deklarativen Gestaltung von Text auf Ansichtsebene,
TextView
dem Stil der gesamten
TextView
während des Füllens. Jeder nach dem Füllen angewendete Stil (z. B.
textView.setTextColor(…)
) überschreibt das deklarative Styling.
TextView
unterstützt auch kleinere Stile über
Span
. Ich werde nicht auf dieses Thema eingehen, da es in Artikeln von
Florina Muntenescu ausführlich beschrieben wird.
→
Spantastisches Textstyling mit Spans→
Überspannende BereicheIch werde dies der Vollständigkeit halber erwähnen, um zu berücksichtigen, dass Programmstil und -spannen ganz oben auf der Prioritätsreihenfolge stehen:
Bereich → Setter → Ansicht → Stil → Standardstil → Thema → TextdarstellungWählen Sie Ihren Stil
Obwohl es verschiedene Möglichkeiten gibt, Ihren Text zu formatieren, hilft Ihnen das Verständnis der Unterschiede zwischen Methoden und ihrer Einschränkungen, das richtige Werkzeug für eine bestimmte Aufgabe zu finden oder zu verstehen, warum eine Methode Vorrang vor einer anderen hat.
Habt einen schönen Text Styling!
Wir laden alle zu einem
kostenlosen Webinar ein, in dessen Rahmen wir uns mit dem DI-Framework Dagger 2 vertraut machen werden: Wir werden untersuchen, wie Dagger2 Code generiert, wir werden mit JSR 330-Annotationen und Dagger2-Konstrukten umgehen, wir werden lernen, wie Dagger2 in einer Multimodul-Anwendung verwendet wird, und den Dagger Android Injector in Betracht ziehen.