2016-03-25 11 views
2

Android uygulamasında bir Xamarin Android uygulamasında özel bir yazı tipi uygulamak için özel bir LabelRenderer oluşturdum (https://developer.xamarin.com/guides/xamarin-forms/user-interface/text/fonts/).Xamarin.Forms'taki Özel Yazı Tipi BiçimlendirilmişString ile

.Text özelliğine eklenen içerikle normal bir etiket için her şey harika çalışıyor. Ancak, .FormattedText özelliğini kullanarak bir etiket oluşturursam, özel yazı tipi uygulanmaz.

Bunu yapan herkes başarıya sahip midir? Bir seçenek, sadece farklı büyüklükteki metin satırlarını dizdiğimden, her biri için ayrı etiket denetimleri kullanmaktır, ancak mümkünse biçimlendirilmiş bir dize kullanmayı tercih ederim. öyle her iOS yazı tipini uygulamak ve kadar Android için yazı tipini uygulayarak bırakır ...

[assembly: ExportRenderer (typeof (gbrLabel), typeof (gbrLabelRenderer))] 

public class gbrLabelRenderer: LabelRenderer 
{ 
    protected override void OnElementChanged (ElementChangedEventArgs<Label> e) 
    { 
     base.OnElementChanged (e); 
     var label = (TextView)Control; 
     Typeface font = Typeface.CreateFromAsset (Forms.Context.Assets, "Lobster-Regular.ttf"); 
     label.Typeface = font; 
    } 
} 

Ve işte benim basit etiket kontrolü var:

İşte benim özel renderer bağırsaklar var özel oluşturucu.

public class gbrLabel: Label 
{ 
    public gbrLabel() 
    { 
     Device.OnPlatform (
      iOS:() => { 
       FontFamily = "Lobster-Regular"; 
       FontSize = Device.GetNamedSize(NamedSize.Medium,this); 
      } 
    } 
} 

İşleri sadece .Text özelliğiyle etiketler için ince ... ama .FormattedText özelliğiyle etiketler için.

Kazıya devam etmeli miyim yoksa etiketlerimi yığmalı mıyım? talep beri Burada

, ben Biçimlendirilmiş metinde bu denedim çeşitli şekillerde bir örnek:

var fs = new FormattedString(); 
fs.Spans.Add (new Span { 
    Text = string.Format("LINE 1\n",Title), 
    FontSize = Device.GetNamedSize(NamedSize.Large,typeof(Label)) 
}); 
fs.Spans.Add (new Span { 
    Text = string.Format ("LINE 2\n"), 
    FontSize = Device.GetNamedSize(NamedSize.Large,typeof(Label)) * 2, 
    FontAttributes = FontAttributes.Bold, 
    FontFamily = "Lobster-Regular" 
}); 
fs.Spans.Add (new Span { 
    Text = string.Format ("LINE 3\n"), 
    FontSize = Device.GetNamedSize(NamedSize.Medium,typeof(Label)), 
    FontFamily = "Lobster-Regular.ttf" 
}); 

gbrLabel lblContent = new gbrLabel { 
    FormattedText = fs 
} 

Bunların hiçbiri (birinci, varsayılan sınıf/Oluşturucu tarafından ayarlanmalı ve ikinci 2, bir yayılma tanımlamasında fontun dahil edilmesinin çeşitliliğidir) Android'de çalışma.

+0

Olası kopyalar http://stackoverflow.com/questions/28407417/change-typeface-of-formatted güzel renkli Metin :) olduğunu -text-in-xamarin) –

+0

Doğru, çok benzer ... hiç kimse bu soruya iyi bir cevap vermedi. Daha önce hiç bir dupe sormadım - sorularımı tazeleştirmek için oradaki soruyu taşıyabilir miyim? –

+0

Bu cevaptan neyin eksik? Her yayılma için yazı tipini ayarlayabilirsiniz. Veya hedefiniz, yazı tipini arka planda tüm Etiketlere göre ayarlamak, böylece manuel olarak ayarlamanıza gerek kalmaz mı? –

cevap

18

Not: Android ve iOS sorunları bir blog yayınında özetlenmiştir: smstuebe.de/2016/04/03/formattedtext.xamrin.forms/


yazı sürece FontSize veya FontAttributes ayarlamayın olarak ayarlanır. Bu yüzden uygulamaya baktım ve FormattedText'un yazı tipini Android'de çalışmayan varsayılan oluşturucu gibi yüklemeye çalıştığını gördüm.

Android biçimlendirme sistemi Xamarin.Forms'unkine çok benziyor. Metin niteliklerini tanımlamak için açıklıklar kullanıyor. Oluşturucu, her bir Span için özel bir yazı tipi, boyutu veya özniteliği olan FontSpan ekliyor. Ne yazık ki, FontSpan sınıfı, FormattedStringExtensions özel bir iç sınıftır, bu yüzden yansımaları ele almak zorundayız.

Bizim Renderer, Control.TextFormatted başlatılıyor ve FormattedText özelliği değiştiğinde güncelleştiriliyor. Güncelleme yönteminde, tüm FontSpan s'yi aldık ve bunları CustomTypefaceSpan ile değiştirin.

Renderer

public class FormattedLabelRenderer : LabelRenderer 
{ 
    private static readonly Typeface Font = Typeface.CreateFromAsset(Forms.Context.Assets, "LobsterTwo-Regular.ttf"); 
    protected override void OnElementChanged(ElementChangedEventArgs<Label> e) 
    { 
     base.OnElementChanged(e); 
     Control.Typeface = Font; 
     UpdateFormattedText(); 
    } 

    private void UpdateFormattedText() 
    { 
     if (Element.FormattedText != null) 
     { 
      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, 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) 
     { 
      UpdateFormattedText(); 
     } 
    } 
} 

Yeni bir eleman türü gbrLabel tanıtıldı neden, emin değilim, ama sürece sadece oluşturucusunu değiştirmek için wan't olarak, oluşturmak gerekmez özel bir öğe.Varsayılan elemanının oluşturucusunu değiştirebilirsiniz:

[assembly: ExportRenderer(typeof(Label), typeof(FormattedLabelRenderer))] 

CustomTypefaceSpan

public class CustomTypefaceSpan : MetricAffectingSpan 
{ 
    private readonly Typeface _typeFace; 
    private readonly Typeface _typeFaceBold; 
    private readonly Typeface _typeFaceItalic; 
    private readonly Typeface _typeFaceBoldItalic; 
    private readonly TextView _textView; 
    private Font _font; 

    public CustomTypefaceSpan(TextView textView, Font font) 
    { 
     _textView = textView; 
     _font = font; 
     // Note: we are ignoring _font.FontFamily (but thats easy to change) 
     _typeFace = Typeface.CreateFromAsset(Forms.Context.Assets, "LobsterTwo-Regular.ttf"); 
     _typeFaceBold = Typeface.CreateFromAsset(Forms.Context.Assets, "LobsterTwo-Bold.ttf"); 
     _typeFaceItalic = Typeface.CreateFromAsset(Forms.Context.Assets, "LobsterTwo-Italic.ttf"); 
     _typeFaceBoldItalic = Typeface.CreateFromAsset(Forms.Context.Assets, "LobsterTwo-BoldItalic.ttf"); 
    } 

    public override void UpdateDrawState(TextPaint paint) 
    { 
     ApplyCustomTypeFace(paint); 
    } 

    public override void UpdateMeasureState(TextPaint paint) 
    { 
     ApplyCustomTypeFace(paint); 
    } 

    private void ApplyCustomTypeFace(Paint paint) 
    { 
     var tf = _typeFace; 

     if (_font.FontAttributes.HasFlag(FontAttributes.Bold) && _font.FontAttributes.HasFlag(FontAttributes.Italic)) 
     { 
      tf = _typeFaceBoldItalic; 
     } 
     else if (_font.FontAttributes.HasFlag(FontAttributes.Bold)) 
     { 
      tf = _typeFaceBold; 
     } 
     else if (_font.FontAttributes.HasFlag(FontAttributes.Italic)) 
     { 
      tf = _typeFaceItalic; 
     } 

     paint.SetTypeface(tf); 
     paint.TextSize = TypedValue.ApplyDimension(ComplexUnitType.Sp, _font.ToScaledPixel(), _textView.Resources.DisplayMetrics); 
    } 
} 

Bizim Custom CustomTypefaceSpan Xamarin.Forms ait FontSpan benzer, ancak özel yazı tipleri yükleme ve farklı yükleyebilirsiniz Farklı FontAttributes için yazı tipleri.

sonuç enter image description here

[Xamarin biçimlendirilmiş metnin Değişim yazı tipinde] (içinde
+0

satır:; 'var açıklıklı = ss.GetSpans (. 0, ss.ToString() uzunluğu, Class.FromType (tip)) derleme sırasında ' Bana bir hataya neden mi: ' [...]/FormattedLabelRenderer.cs (60,60): Hata CS0176: Statik üye Java.Lang.Class.FromType (System.Type) bir örnek başvurusu ile erişilemiyor, bunun yerine bir tür adıyla nitelendir (CS0176) (GbrEvents.Droid) ' . Bunun tam olarak ne anlama geldiğini bulmaya çalışıyorum ... belki de bir kullanma ifadesini kaçırmıyorum? –

+1

'Class' ayrıca, Render uygulamasının bir özelliğidir, çünkü Java.Lang.Object öğesinden devralınır. Tam adı Java.Lang.Class.FromType 'kullanmayı deneyebilir misiniz? veya Java.Lang kullanarak '' kullanıyorum; –

+0

Daha önce Java.Lang kullanmayı denedim; ... yardım etmedi. Tamamen nitelikli referans eklemek hile yaptı, ancak ... İşler mükemmel! Muhtemelen sınıfta başka bir kullanım ifadesi vardı, kafam karıştı. Haydi, yazı tipleri, boyutlar ve renkler ile oynama zamanı. –