Skip to content

Instantly share code, notes, and snippets.

@alexlau811
Created March 8, 2015 10:53
Show Gist options
  • Save alexlau811/8d8ddbae84d639f2ce11 to your computer and use it in GitHub Desktop.
Save alexlau811/8d8ddbae84d639f2ce11 to your computer and use it in GitHub Desktop.
Override default FormattedString behaviour to allow custom font to be used in Label of Xamarin.Forms.Android
public static class OverrideFormattedStringExtension
{
//
// Static Methods
//
public static SpannableString ToAttributed(this FormattedString formattedString, Font defaultFont, Color defaultForegroundColor, TextView view)
{
if (formattedString == null)
{
return null;
}
StringBuilder stringBuilder = new StringBuilder();
foreach (Span current in formattedString.Spans)
{
if (current.Text != null)
{
stringBuilder.Append(current.Text);
}
}
SpannableString spannableString = new SpannableString(stringBuilder.ToString());
int num = 0;
foreach (Span current2 in formattedString.Spans)
{
if (current2.Text != null)
{
int num2 = num;
int num3 = num2 + current2.Text.Length;
num = num3;
if (current2.ForegroundColor != Color.Default)
{
spannableString.SetSpan(new ForegroundColorSpan(current2.ForegroundColor.ToAndroid()), num2, num3, SpanTypes.InclusiveExclusive);
}
else
{
if (defaultForegroundColor != Color.Default)
{
spannableString.SetSpan(new ForegroundColorSpan(defaultForegroundColor.ToAndroid()), num2, num3, SpanTypes.InclusiveExclusive);
}
}
if (current2.BackgroundColor != Color.Default)
{
spannableString.SetSpan(new BackgroundColorSpan(current2.BackgroundColor.ToAndroid()), num2, num3, SpanTypes.InclusiveExclusive);
}
if (! IsSpanDefault(current2))
{
spannableString.SetSpan(new FontSpan(current2.Font, view), num2, num3, SpanTypes.InclusiveInclusive);
}
else
{
if (defaultFont != Font.Default)
{
spannableString.SetSpan(new FontSpan(defaultFont, view), num2, num3, SpanTypes.InclusiveInclusive);
}
}
}
}
return spannableString;
}
public static bool IsSpanDefault(Span self)
{
return self.FontFamily == null && self.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Label)) && self.FontAttributes == FontAttributes.None;
}
//
// Nested Types
//
private class FontSpan : MetricAffectingSpan
{
public Font Font
{
get;
private set;
}
public TextView TextView
{
get;
private set;
}
public FontSpan(Font font, TextView view)
{
this.Font = font;
this.TextView = view;
}
public override void UpdateDrawState(TextPaint tp)
{
this.Apply(tp);
}
public override void UpdateMeasureState(TextPaint p)
{
this.Apply(p);
}
private void Apply(Paint paint)
{
paint.SetTypeface(this.Font.ToTypeface());
float value = this.Font.ToScaledPixel();
paint.TextSize = TypedValue.ApplyDimension(ComplexUnitType.Sp, value, this.TextView.Resources.DisplayMetrics);
}
}
public static Typeface ToTypeface(this Font self)
{
if (self == Font.Default)
{
return Typeface.Default;
}
TypefaceStyle style = TypefaceStyle.Normal;
if ((self.FontAttributes & (FontAttributes.Bold | FontAttributes.Italic)) == (FontAttributes.Bold | FontAttributes.Italic))
{
style = TypefaceStyle.BoldItalic;
}
else
{
if ((self.FontAttributes & FontAttributes.Bold) != FontAttributes.None)
{
style = TypefaceStyle.Bold;
}
else
{
if ((self.FontAttributes & FontAttributes.Italic) != FontAttributes.None)
{
style = TypefaceStyle.Italic;
}
}
}
if (self.FontFamily != null)
{
var typeface = Typeface.Create(self.FontFamily, style);
if (typeface.Equals(Typeface.Default))
{
try
{
return Typeface.CreateFromAsset(Android.App.Application.Context.Assets, "fonts/" + self.FontFamily);
}
catch (Exception ex)
{
try
{
return Typeface.CreateFromFile("fonts/" + self.FontFamily);
}
catch (Exception ex1)
{
return typeface; // which is Typeface.Default
}
}
}
return typeface; // which is Typeface.Default
}
return Typeface.Create(Typeface.Default, style);
}
}
[assembly: ExportRenderer(typeof(Label), typeof(OverrideLabelRenderer))]
public class OverrideLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
this.UpdateText();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Label.TextColorProperty.PropertyName)
{
this.UpdateText();
return;
}
if (e.PropertyName == Label.FontProperty.PropertyName)
{
this.UpdateText();
return;
}
if (e.PropertyName == Label.TextProperty.PropertyName || e.PropertyName == Label.FormattedTextProperty.PropertyName)
{
this.UpdateText();
}
}
private void UpdateText()
{
if (base.Element.FormattedText != null)
{
var view = Control as TextView;
FormattedString formattedString = base.Element.FormattedText ?? base.Element.Text;
view.TextFormatted = formattedString.ToAttributed(base.Element.Font, base.Element.TextColor, view);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment