Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin.Forms: the MultiLineLabel doesn't longer work on Android

On my Xamarin.Forms project, I use a MultiLineLabel to display a title on 1 or 2 lines, depending the text length. I'm based on this blog to achieve this.

So I have a MultiLineLabel control:

public class MultiLineLabel : Label
{
    private static int _defaultLineSetting = -1;

    public static readonly BindableProperty LinesProperty = BindableProperty.Create(nameof(Lines), typeof(int), typeof(MultiLineLabel), _defaultLineSetting);
    public int Lines
    {
        get { return (int)GetValue(LinesProperty); }
        set { SetValue(LinesProperty, value); }
    }
}

I use 2 renderers:

  • on iOS, I've kept the given renderer:

    public class CustomMultiLineLabelRenderer : LabelRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);
    
            MultiLineLabel multiLineLabel = (MultiLineLabel)Element;
    
            if (multiLineLabel != null && multiLineLabel.Lines != -1)
                Control.Lines = multiLineLabel.Lines;
    
        }
    }
    
  • on Android I've customized the renderer:

    public class CustomMultiLineLabelRenderer : LabelRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);
    
            MultiLineLabel multiLineLabel = (MultiLineLabel)Element;
    
            if (multiLineLabel != null && multiLineLabel.Lines != -1)
            {
                Control.Ellipsize = TextUtils.TruncateAt.End;
                Control.SetMaxLines(multiLineLabel.Lines);
            }
        }
    }
    

And I use this MultiLineLabel like this in XAML:

<StackLayout 
    Grid.Row="0"
    Spacing="0">

    <local:MultiLineLabel
        Margin="8,6,8,0"
        TextColor="{ DynamicResource InverseTextColor }"
        Text="{ Binding encart_titre }"
        FontSize="{ artina:OnOrientationDouble 
            Default=16,
            PortraitTablet=20,
            LandscapeTablet=20 }"
        LineBreakMode="TailTruncation"
        Lines="2"
        Grid.Column="0"
        BackgroundColor="Yellow"
    />
</StackLayout>

Until I used Xamarin.Forms v.2.3.4.247, this worked well on Android:

screenshot before update

But after having updated to the latest version (Xamarin.Forms v.2.4.0.269-pre2), it doesn't longer work as expected:

screenshot after update

I also tried to use the renderer given on the blog:

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

    MultiLineLabel multiLineLabel = (MultiLineLabel)Element;

    if (multiLineLabel != null && multiLineLabel.Lines != -1)
    {
        Control.SetSingleLine(false);
        Control.SetLines(multiLineLabel.Lines);
    }
}

But I didn't get the expected rendering: screenshot after updater - alternative

Would you have any explanation? Or another suggestion? On iOS this works well.

like image 595
Gold.strike Avatar asked Sep 04 '17 18:09

Gold.strike


People also ask

Is Xamarin deprecated Android?

Not dead but possibly moribund. In May 2020, Microsoft announced that Xamarin. Forms, a major component of its mobile app development framework, would be deprecated in November 2021 in favour of a new . Net based product called MAUI - Multiform App User Interface.

What is the difference between Xamarin forms and Xamarin Android?

Generally, the main distinction between the two platforms is that Xamarin. Forms allows reusing the same UI code for multiple OS, whereas Xamarin Native is adapted to APIs, specific to a specific platform – Windows, iOS, Android.

How does Xamarin work on Android?

Xamarin. Android applications compile from C# into Intermediate Language (IL) which is then Just-in-Time (JIT) compiled to a native assembly when the application launches. Xamarin. Android applications run within the Mono execution environment, side by side with the Android Runtime (ART) virtual machine.

What is LineBreakMode in Xamarin forms?

If you have a text that is to large to fit the width of your label, you can use the attribute called LineBreakMode=TailTruncation. This will display a text with “…” at the end (ellipsis) when the text doesn't fit. Let's take for example this text: “Welcome to Xamarin Forms” inside a Label like in the exmple below: <?


1 Answers

But after having updated to the latest version (Xamarin.Forms v.2.4.0.269-pre2), it doesn't longer work as expected:

Cause:

I've checked the source codes of Xamarin.Forms v.2.4.0.269-pre2. In LabelRenderer's OnElementChange event, FormsTextView's SetLineBreakMode will be called which contains following codes:

public static void SetLineBreakMode(this TextView textView, LineBreakMode lineBreakMode)
{
    switch (lineBreakMode)
    {
        case LineBreakMode.NoWrap:
            textView.SetMaxLines(1);
            textView.SetSingleLine(true);
            textView.Ellipsize = null;
            break;
        case LineBreakMode.WordWrap:
            textView.Ellipsize = null;
            textView.SetMaxLines(100);
            textView.SetSingleLine(false);
            break;
        case LineBreakMode.CharacterWrap:
            textView.Ellipsize = null;
            textView.SetMaxLines(100);
            textView.SetSingleLine(false);
            break;
        case LineBreakMode.HeadTruncation:
            textView.SetMaxLines(1);
            textView.SetSingleLine(true);
            textView.Ellipsize = TextUtils.TruncateAt.Start;
            break;
        case LineBreakMode.TailTruncation:
            textView.SetMaxLines(1);
            textView.SetSingleLine(true);
            textView.Ellipsize = TextUtils.TruncateAt.End;
            break;
        case LineBreakMode.MiddleTruncation:
            textView.SetMaxLines(1);
            textView.SetSingleLine(true);
            textView.Ellipsize = TextUtils.TruncateAt.Middle;
            break;
    }
}

As you can see, if you use LineBreakMode.TailTruncation, textView.SetMaxLines(1); and textView.SetSingleLine(true); will be called, which disable the multi line function.(In 2.3.4 textView.SetSingleLine(true); doesn't exist).

Solution:

To fix the problem, you simply need to add two lines of codes in your renderer:

protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Label> e)
{
    base.OnElementChanged(e);
    MultiLineLabel multiLineLabel = (MultiLineLabel)Element;

    if (multiLineLabel != null && multiLineLabel.Lines != -1)
    {
        Control.SetSingleLine(false);
        Control.SetMaxLines(multiLineLabel.Lines);
        Control.SetLines(multiLineLabel.Lines);

    }
}
like image 93
Elvis Xia - MSFT Avatar answered Oct 11 '22 06:10

Elvis Xia - MSFT