Je n'ai pas trouvé de moyen de le faire. C'est possible?
Eh bien, je ne pouvais pas comprendre comment le faire avec les classes disponibles, j'ai donc étendu le TypefaceSpan
par moi-même et maintenant cela fonctionne pour moi. Voici ce que j'ai fait:
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);
}
}
Bien que notme ait essentiellement la bonne idée, la solution proposée est un peu hacky car la "famille" devient superflue. Il est également légèrement incorrect car TypefaceSpan est l'une des plages spéciales que Android connaît et attend certains comportements par rapport à l'interface ParcelableSpan (dont la sous-classe de notme ne fonctionne pas correctement, ni possible, mettre en place).
Une solution plus simple et plus précise serait:
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);
}
}
Si quelqu'un est intéressé, voici la version C # Xamarin du code de Benjamin:
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);
}
}
}
Et utilisation: (en activité 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;