我已经按照Sven的示例为formatstrings的自定义字体:https://github.com/smstuebe/xamarin-forms-formattedtext
但是,我遇到了一个奇怪的问题,即如果我实现UIFormattedStringLabel(),我的视图上的点击手势就不起作用了。 这是非常奇怪的,因为如果我使用不使用提供的自定义渲染器的常规标签,则会检测到手势,显示格式化的字符串(只是字体是默认的)并且所有内容都正确加载。
所以,我认为设置上面的渲染器存在问题,因为问题似乎源于此。也许,我错过了我想要做的一步。
using Android.Graphics;
using Android.Text;
using Android.Text.Style;
using Android.Util;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
namespace Proj.Droid.CustomRenderer
{
public class CustomTypefaceSpan : MetricAffectingSpan
{
private readonly Typeface _typeFace;
private readonly TextView _textView;
private Font _font;
public CustomTypefaceSpan(TextView textView, Label label, Font font)
{
_textView = textView;
_font = font;
_typeFace = Typeface.CreateFromAsset(Forms.Context.Assets, GetFontName(_font.FontFamily ?? label.FontFamily, _font.FontAttributes));
}
private static string GetFontName(string fontFamily, FontAttributes fontAttributes)
{
var postfix = "Regular";
var bold = fontAttributes.HasFlag(FontAttributes.Bold);
var italic = fontAttributes.HasFlag(FontAttributes.Italic);
if (bold && italic) { postfix = "BoldItalic"; }
else if (bold) { postfix = "Bold"; }
else if (italic) { postfix = "Italic"; }
return $"{fontFamily}-{postfix}.otf";
}
public override void UpdateDrawState(TextPaint paint)
{
ApplyCustomTypeFace(paint);
}
public override void UpdateMeasureState(TextPaint paint)
{
ApplyCustomTypeFace(paint);
}
private void ApplyCustomTypeFace(Paint paint)
{
paint.SetTypeface(_typeFace);
paint.TextSize = TypedValue.ApplyDimension(ComplexUnitType.Sp, _font.ToScaledPixel(), _textView.Resources.DisplayMetrics);
}
}
}
using System.ComponentModel;
using System.Reflection;
using Android.Graphics;
using Android.Text;
using Java.Lang;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Proj.Droid.CustomRenderer;
using Proj.Core.UI.XamarinForms.Controls;
using System;
[assembly: ExportRenderer(typeof(UIFormattedStringLabel), typeof(FormattedLabelRenderer))]
namespace Proj.Droid.CustomRenderer
{
public class SimpleLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Typeface = Typeface.CreateFromAsset(Forms.Context.Assets, GetFontName(Element.FontFamily, Element.FontAttributes));
}
}
private static string GetFontName(string fontFamily, FontAttributes fontAttributes)
{
var postfix = "Regular";
var bold = fontAttributes.HasFlag(FontAttributes.Bold);
var italic = fontAttributes.HasFlag(FontAttributes.Italic);
if (bold && italic) { postfix = "BoldItalic"; }
else if (bold) { postfix = "Bold"; }
else if (italic) { postfix = "Italic"; }
return $"{fontFamily}-{postfix}.otf";
}
}
public class FormattedLabelRenderer : SimpleLabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
UpdateFormattedText();
}
private void UpdateFormattedText()
{
if (Element?.FormattedText == null)
return;
var extensionType = typeof(FormattedStringExtensions);
var type = extensionType.GetNestedType("FontSpan", BindingFlags.NonPublic);
var ss = new SpannableString(Control.TextFormatted);
var spans = ss.GetSpans(0, ss.ToString().Length, Class.FromType(type));
foreach (var span in spans)
{
var start = ss.GetSpanStart(span);
var end = ss.GetSpanEnd(span);
var flags = ss.GetSpanFlags(span);
var font = (Font)type.GetProperty("Font").GetValue(span, null);
ss.RemoveSpan(span);
var newSpan = new CustomTypefaceSpan(Control, Element, font);
ss.SetSpan(newSpan, start, end, flags);
}
Control.TextFormatted = ss;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Label.FormattedTextProperty.PropertyName ||
e.PropertyName == Label.TextProperty.PropertyName ||
e.PropertyName == Label.FontAttributesProperty.PropertyName ||
e.PropertyName == Label.FontProperty.PropertyName ||
e.PropertyName == Label.FontSizeProperty.PropertyName ||
e.PropertyName == Label.FontFamilyProperty.PropertyName ||
e.PropertyName == Label.TextColorProperty.PropertyName)
{
UpdateFormattedText();
}
}
}
}
using System;
using Xamarin.Forms;
using XLabs.Forms.Controls;
namespace Proj.Core.UI.XamarinForms.Controls
{
public class UIFormattedStringLabel : Label
{
public UIFormattedStringLabel()
{
}
}
}
标签代码:
var formatString = new FormattedString();
formatString.Spans.Add(new Span { Text = Time.Text + "\n", FontAttributes = FontAttributes.Bold, ForegroundColor = ColorHelper.FromHex(CoreTheme.COLOR_DARK_GREY)});
formatString.Spans.Add(new Span { Text = TimeRemaining.Text, FontAttributes = FontAttributes.Bold,ForegroundColor = ColorHelper.FromHex(CoreTheme.COLOR_DEFAULT_BLACK)});
labelTime = new UIFormattedStringLabel();
labelTime.ClassId = offerid.ToString();
labelTime.WidthRequest = (DeviceDisplaySettings.defaultwidth / buttonsToShow) - 10;
labelTime.HeightRequest = 40;
labelTime.VerticalTextAlignment = TextAlignment.Center;
labelTime.BackgroundColor = ColorHelper.FromHex(CoreTheme.COLOR_LIGHT_GREY);
labelTime.FormattedText = formatString;
答案 0 :(得分:2)
正如我在博文中提到的,渲染器并不完美。在您的情况下,如果FontFamily
的{{1}}为空且Label
的{{1}}为空,则会崩溃。
我在存储库中添加了一些修复程序。 https://github.com/smstuebe/xamarin-forms-formattedtext/commit/d3b9eab7f588917f1e4417188a12e66f97cf1081
FontFamily
如果我们有字体集,我们只会替换范围。
Span
我不会在UpdateFormattedText
中检查是否为null,因为它会显示您的字体未正确加载,并且您必须仔细检查名称和资产。
答案 1 :(得分:0)
使用SetTypeface方法设置字体。如下更改渲染器可能会修复它
class FormattedStringLabelRender : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
var label = (TextView)Control; // for example
Typeface font = Typeface.CreateFromAsset(Forms.Context.Assets, "Fonts/ProximaNova-Bold.otf"); // font name specified here
label.SetTypeface (font, TypefaceStyle.Normal);
}
}