Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way that I can use Spans inside of a label and also have it justified?

I am using this code to add some colors to my text inside of a label:

<Label.FormattedText>
  <FormattedString>
     <Span Text="I would like the word " />
     <Span Text="HERE" ForegroundColor="Red" FontAttributes="Bold" />
     <Span Text="to be in a bold font" />
   </FormattedString>
</Label.FormattedText>

Previously I had been using this rendering code to justify the label:

public class JustifiedLabelRenderer : LabelRenderer
{
    public JustifiedLabelRenderer() {}

    protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
    {
        base.OnElementChanged(e);

        //if we have a new forms element, we want to update text with font style (as specified in forms-pcl) on native control
        if (e.NewElement != null)
            UpdateTextOnControl();
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        //if there is change in text or font-style, trigger update to redraw control
        if (e.PropertyName == nameof(Label.Text)
           || e.PropertyName == nameof(Label.FontFamily)
           || e.PropertyName == nameof(Label.FontSize)
           || e.PropertyName == nameof(Label.TextColor)
           || e.PropertyName == nameof(Label.FontAttributes))
        {
            UpdateTextOnControl();
        }
    }

    void UpdateTextOnControl()
    {
        if (Control == null)
            return;

        //define paragraph-style
        var style = new NSMutableParagraphStyle()
        {
            Alignment = UITextAlignment.Justified,
            FirstLineHeadIndent = 0.001f,
        };

        //define attributes that use both paragraph-style, and font-style 
        var uiAttr = new UIStringAttributes()
        {
            ParagraphStyle = style,
            BaselineOffset = 0,

            Font = Control.Font
        };

        //define frame to ensure justify alignment is applied
        Control.Frame = new System.Drawing.RectangleF(0, 0, (float)Element.Width, (float)Element.Height);

        //set new text with ui-style-attributes to native control (UILabel)
        var stringToJustify = Control.Text ?? string.Empty;
        var attributedString = new Foundation.NSAttributedString(stringToJustify, uiAttr.Dictionary);
        Control.AttributedText = attributedString;
        Control.Lines = 0;
    }

When I try using this code to have a colored justified label the changes to the span font and color don't show up any more.

Is there a way that I could have a label that is both justified and also has color spans inside of it?

Here's my XAML definition of the label I am using:

<local:JustifiedLabel x:Name="c0Label" />

Here's the code that populates it:

var s = new FormattedString();
s.Spans.Add(new Span { Text = "test words test words test words test words test words test words", ForegroundColor = Color.Red});
s.Spans.Add(new Span { Text = "ABCDEFG", ForegroundColor = Color.Black });
s.Spans.Add(new Span { Text = " test words test words test words test words test words test words test words test words test words test words test words test words ", ForegroundColor = Color.FromHex("555555") });
c0Label.FormattedText = s;
like image 307
Samantha J T Star Avatar asked Oct 27 '17 08:10

Samantha J T Star


1 Answers

You will have to update the renderer to consider FormattedText. For e.g.: try changing renderer logic to following:

public class JustifiedLabelRenderer : LabelRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
    {
        base.OnElementChanged(e);

        //if we have a new forms element, update text
        if (e.NewElement != null)
            UpdateTextOnControl();
    }

    protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        //if there is change in formatted-text, trigger update to redraw control
        if (e.PropertyName == nameof(Label.FormattedText))
        {
            UpdateTextOnControl();
        }
    }

    void UpdateTextOnControl()
    {
        if (Control == null)
            return;

        //define paragraph-style
        var style = new NSMutableParagraphStyle()
        {
            Alignment = UITextAlignment.Justified,
            FirstLineHeadIndent = 0.001f,

        };

        //define frame to ensure justify alignment is applied
        Control.Frame = new RectangleF(0, 0, (float)Element.Width, (float)Element.Height);
        Control.Lines = 0;

        if (Element.FormattedText.ToAttributed(Element.Font, Element.TextColor) is NSMutableAttributedString attrText)
        {
            var fullRange = new NSRange(0, attrText.Length);
            attrText.AddAttribute(UIStringAttributeKey.ParagraphStyle, style, fullRange);
            Control.AttributedText = attrText;
        }
    }
}
like image 53
Sharada Gururaj Avatar answered Oct 11 '22 21:10

Sharada Gururaj