Xamarin.Forms: MultiLineLabel больше не работает на Android

В моем проекте Xamarin.Forms я использую MultiLineLabel для отображения заголовка в 1 или 2 строки, в зависимости от длины текста. Я основываюсь на этом blog, чтобы добиться этого.

Итак, у меня есть MultiLineLabel элемент управления:

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); }
    }
}

Я использую 2 модуля рендеринга:

  • в iOS я сохранил данное средство визуализации:

    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;
    
        }
    }
    
  • на Android я настроил средство визуализации:

    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);
            }
        }
    }
    

И я использую эту MultiLineLabel в 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>

Пока я не использовал Xamarin.Forms v.2.3.4.247, это хорошо работало на Android:

снимок экрана перед обновлением

Но после обновления до последней версии (Xamarin.Forms v.2.4.0.269-pre2) он больше не работает должным образом:

снимок экрана после обновления

Я также пробовал использовать средство визуализации, указанное в блоге:

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);
    }
}

Но я не получил ожидаемого рендеринга:  снимок экрана после средства обновления - альтернатива

Не могли бы вы объяснить? Или другое предложение? На iOS это хорошо работает.


person Gold.strike    schedule 04.09.2017    source источник


Ответы (1)


Но после обновления до последней версии (Xamarin.Forms v.2.4.0.269-pre2) он больше не работает должным образом:

Причина:

Я проверил исходники Xamarin.Forms v.2.4.0.269-pre2. В событии OnElementChange LabelRenderer будет вызываться SetLineBreakMode FormsTextView, которое содержит следующие коды:

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;
    }
}

Как видите, если вы используете LineBreakMode.TailTruncation, будут вызываться textView.SetMaxLines(1); и textView.SetSingleLine(true);, которые отключают многострочную функцию (в 2.3.4 textView.SetSingleLine(true); не существует).

Решение:

Чтобы решить эту проблему, вам просто нужно добавить две строки кода в свой рендерер:

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);

    }
}
person Elvis Xia - MSFT    schedule 05.09.2017
comment
Привет, @Elvis Xia, спасибо за отзыв. Я использую его без строки Control.SetLines(multiLineLabel.Lines);, так как хочу, чтобы метка автоматически расширялась в зависимости от содержимого. - person Gold.strike; 05.09.2017