Wie sieht dein Text aus?

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 Illustration

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

Ich würde das folgende Verfahren für das Styling vorschlagen:

  1. textViewStyle Sie einen beliebigen Anwendungsstil in textViewStyle als Standardstil für Ihr Thema fest.
  2. 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
  3. Erstellen Sie einen style indem Sie Attribute TextAppearance die von TextAppearance nicht unterstützt werden (die selbst einen Ihrer TextAppearance ).
  4. 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 → Stil

Direkt 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(); } // a little later a = theme.obtainStyledAttributes(attrs, com.android.internal.R.styleable.TextView, defStyleAttr, defStyleRes); readTextAppearance(context, a, attributes, true); 

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

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

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

  1. Alle Attributwerte in diesem AttributeSet.
  2. Die im AttributeSet angegebene Stilressource (mit dem Namen "style").
  3. Der von defStyleAttr und defstyleres angegebene Standardstil
  4. Grundwerte in diesem Thread.

Styling Priority Order aus der Themendokumentation

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


Standardknopf

Warum? 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 -> Textdarstellung

Im 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 → Textdarstellung

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

Ich 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 → Textdarstellung

Wä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.

Source: https://habr.com/ru/post/de456110/


All Articles