Ich habe keinen Weg gefunden, dies zu tun. Ist es möglich?
76
Nun, ich konnte nicht herausfinden, wie ich es mit den verfügbaren Klassen machen soll, also habe ich die selbst erweitert und TypefaceSpan
jetzt funktioniert es für mich. Folgendes habe ich getan:
package de.myproject.text.style;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.text.style.TypefaceSpan;
public class CustomTypefaceSpan extends TypefaceSpan {
private final Typeface newType;
public CustomTypefaceSpan(String family, Typeface type) {
super(family);
newType = type;
}
@Override
public void updateDrawState(TextPaint ds) {
applyCustomTypeFace(ds, newType);
}
@Override
public void updateMeasureState(TextPaint paint) {
applyCustomTypeFace(paint, newType);
}
private static void applyCustomTypeFace(Paint paint, Typeface tf) {
int oldStyle;
Typeface old = paint.getTypeface();
if (old == null) {
oldStyle = 0;
} else {
oldStyle = old.getStyle();
}
int fake = oldStyle & ~tf.getStyle();
if ((fake & Typeface.BOLD) != 0) {
paint.setFakeBoldText(true);
}
if ((fake & Typeface.ITALIC) != 0) {
paint.setTextSkewX(-0.25f);
}
paint.setTypeface(tf);
}
}
Während notme im Wesentlichen die richtige Idee hat, ist die angegebene Lösung etwas hackig, da "Familie" überflüssig wird. Es ist auch etwas falsch, da TypefaceSpan einer der speziellen Bereiche ist, die Android kennt und die ein bestimmtes Verhalten in Bezug auf die ParcelableSpan-Schnittstelle erwarten (die von der Unterklasse von notme nicht ordnungsgemäß implementiert wird oder implementiert werden kann).
Eine einfachere und genauere Lösung wäre:
public class CustomTypefaceSpan extends MetricAffectingSpan { private final Typeface typeface; public CustomTypefaceSpan(final Typeface typeface) { this.typeface = typeface; } @Override public void updateDrawState(final TextPaint drawState) { apply(drawState); } @Override public void updateMeasureState(final TextPaint paint) { apply(paint); } private void apply(final Paint paint) { final Typeface oldTypeface = paint.getTypeface(); final int oldStyle = oldTypeface != null ? oldTypeface.getStyle() : 0; final int fakeStyle = oldStyle & ~typeface.getStyle(); if ((fakeStyle & Typeface.BOLD) != 0) { paint.setFakeBoldText(true); } if ((fakeStyle & Typeface.ITALIC) != 0) { paint.setTextSkewX(-0.25f); } paint.setTypeface(typeface); } }
quelle
TypefaceSpan
aber dann zeigt Marco ein funktionierendes Beispiel, das genau das verwendet. Welches ist das richtige? Benjamin hast du dein Beispiel getestet?TypefaceSpan
. Ich schlage nur sehr stark vor, dass Sie nicht sollten . Dies bricht Liscovs Substitutionsprinzip und ist eine äußerst schlechte Praxis. Sie haben eine Klasse unterklassifiziert, die die Schriftart über einenfamily
Namen angibt und parzellierbar ist. Sie haben dieses Verhalten dann vollständig überschrieben und denfamily
Parameter verwirrend und sinnlos gemacht, und dasSpan
ist auch nicht paketierbar.Unter Android P ist es möglich, dieselbe TypefaceSpan-Klasse zu verwenden, die Sie kennen, wie hier gezeigt .
Bei älteren Versionen können Sie jedoch das verwenden, was sie später in dem Video gezeigt haben, über das ich hier geschrieben habe .
quelle
Wenn jemand interessiert wäre, hier ist die C # Xamarin-Version von Benjamins Code:
using System; using Android.Graphics; using Android.Text; using Android.Text.Style; namespace Utils { //https://stackoverflow.com/a/17961854/1996780 /// <summary>A text span which applies <see cref="Android.Graphics.Typeface"/> on text</summary> internal class CustomFontSpan : MetricAffectingSpan { /// <summary>The typeface to apply</summary> public Typeface Typeface { get; } /// <summary>CTor - creates a new instance of the <see cref="CustomFontSpan"/> class</summary> /// <param name="typeface">Typeface to apply</param> /// <exception cref="ArgumentNullException"><paramref name="typeface"/> is null</exception> public CustomFontSpan(Typeface typeface) => Typeface = typeface ?? throw new ArgumentNullException(nameof(typeface)); public override void UpdateDrawState(TextPaint drawState) => Apply(drawState); public override void UpdateMeasureState(TextPaint paint) => Apply(paint); /// <summary>Applies <see cref="Typeface"/></summary> /// <param name="paint"><see cref="Paint"/> to apply <see cref="Typeface"/> on</param> private void Apply(Paint paint) { Typeface oldTypeface = paint.Typeface; var oldStyle = oldTypeface != null ? oldTypeface.Style : 0; var fakeStyle = oldStyle & Typeface.Style; if (fakeStyle.HasFlag(TypefaceStyle.Bold)) paint.FakeBoldText = true; if (fakeStyle.HasFlag(TypefaceStyle.Italic)) paint.TextSkewX = -0.25f; paint.SetTypeface(Typeface); } } }
Und Verwendung: (in Aktivität OnCreate)
var txwLogo = FindViewById<TextView>(Resource.Id.logo); var font = Resources.GetFont(Resource.Font.myFont); var wordtoSpan = new SpannableString(txwLogo.Text); wordtoSpan.SetSpan(new CustomFontSpan(font), 6, 7, SpanTypes.InclusiveInclusive); //One caracter txwLogo.TextFormatted = wordtoSpan;
quelle
Spannbare Schrift: Um eine andere Schriftart für einen Teil des Textes festzulegen , kann eine benutzerdefinierte Schriftart verwendet werden, wie im folgenden Beispiel gezeigt:
spannable.setSpan( new CustomTypefaceSpan("SFUIText-Bold.otf",fontBold), 0, firstWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); spannable.setSpan( new CustomTypefaceSpan("SFUIText-Regular.otf",fontRegular), firstWord.length(), firstWord.length() + lastWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); text.setText( spannable );
Damit der obige Code funktioniert, muss die Klasse CustomTypefaceSpan von der Klasse TypefaceSpan abgeleitet werden. Dies kann wie folgt erfolgen:
public class CustomTypefaceSpan extends TypefaceSpan { private final Typeface newType; public CustomTypefaceSpan(String family, Typeface type) { super(family); newType = type; } @Override public void updateDrawState(TextPaint ds) { applyCustomTypeFace(ds, newType); } @Override public void updateMeasureState(TextPaint paint) { applyCustomTypeFace(paint, newType); } private static void applyCustomTypeFace(Paint paint, Typeface tf) { int oldStyle; Typeface old = paint.getTypeface(); if (old == null) { oldStyle = 0; } else { oldStyle = old.getStyle(); } int fake = oldStyle & ~tf.getStyle(); if ((fake & Typeface.BOLD) != 0) { paint.setFakeBoldText(true); } if ((fake & Typeface.ITALIC) != 0) { paint.setTextSkewX(-0.25f); } paint.setTypeface(tf); } }
quelle