Вот код, который у меня есть:

<StackLayout>
   <Label x:Name="emptyLabel1" FontSize="18" XAlign="Start" TextColor="Gray" />
   <Label x:Name="emptyLabel2" FontSize="18" XAlign="Center" TextColor="Gray" />
   <Label x:Name="emptyLabel3" FontSize="18" XAlign="Center" TextColor="Gray" />
</StackLayout>

Первая многострочная метка начинается слева, но в некоторых рядах справа есть пробелы. 2-я и 3-я многострочные метки расположены по центру и имеют пробелы слева и справа.

Есть ли способ, чтобы все строки надписей полностью заполняли строки полностью заполняющими слева направо o, чтобы первый символ каждой строки всегда располагался слева, а последний символ последнего слова каждой строки всегда был строкой вверх по праву? Обратите внимание, что для этого потребуется несколько слов в каждой строке, чтобы между ними были разные пропуски.

16
Alan2 1 Сен 2017 в 11:08

4 ответа

Лучший ответ

Немного сложно реализовать метку с поддержкой выравнивания по выравниванию, но это возможно с помощью средства визуализации платформы.

Первым шагом будет объявление пользовательского элемента управления в формах проекта.

public class JustifiedLabel : Label { }

Следующий шаг - определить и зарегистрировать визуализатор платформы в iOS. Это просто, так как мы просто комбинируем отформатированную строку со стилем абзаца, чтобы получить то, что мы хотим.

[assembly: ExportRenderer(typeof(JustifiedLabel), typeof(JustifiedLabelRenderer))]
namespace SomeAppNamespace.iOS
{   
    public class JustifiedLabelRenderer : LabelRenderer
    {
        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, System.ComponentModel.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 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;
        }
    }
}

В платформе Android это немного сложнее - поскольку Android не поддерживает выравнивание выравнивания для TextView - поэтому нам нужно будет использовать WebView вместо этого, чтобы получить его для визуализации текста.

( Примечание. . Вы также можете альтернативно использовать библиотеку Android и использовать ее. вместо WebView)

[assembly: ExportRenderer(typeof(JustifiedLabel), typeof(JustifiedLabelRenderer))]
namespace SomeAppNamespace.Droid
{
    //We don't extend from LabelRenderer on purpose as we want to set 
    // our own native control (which is not TextView)
    public class JustifiedLabelRenderer : ViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<View> 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)
            {
                if (Control == null)
                {
                    //register webview as native control
                    var webView = new Android.Webkit.WebView(Context);
                    webView.VerticalScrollBarEnabled = false;
                    webView.HorizontalScrollBarEnabled = false;

                    webView.LoadData("<html><body>&nbsp;</body></html>", "text/html; charset=utf-8", "utf-8");
                    SetNativeControl(webView);
                }

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

        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.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()
        {
            var webView = Control as Android.Webkit.WebView; 
            var formsLabel = Element as Label;

            // create css style from font-style as specified
            var cssStyle = $"margin: 0px; padding: 0px; text-align: justify; color: {ToHexColor(formsLabel.TextColor)}; background-color: {ToHexColor(formsLabel.BackgroundColor)}; font-family: {formsLabel.FontFamily}; font-size: {formsLabel.FontSize}; font-weight: {formsLabel.FontAttributes}";

            // apply that to text 
            var strData =
                $"<html><body style=\"{cssStyle}\">{formsLabel?.Text}</body></html>";

            // and, refresh webview
            webView.LoadData(strData, "text/html; charset=utf-8", "utf-8");
            webView.Reload();
        }

        // helper method to convert forms-color to css-color
        string ToHexColor(Color color)
        {
            var red = (int)(color.R * 255);
            var green = (int)(color.G * 255);
            var blue = (int)(color.B * 255);
            var alpha = (int)(color.A * 255);
            var hex = $"#{red:X2}{green:X2}{blue:X2}";

            return hex;
        }
    }
}

Пример использования

<StackLayout Margin="20">
    <Entry x:Name="InputEntry" />

    <Label Margin="0,10,0,0" BackgroundColor="Navy" TextColor="White" Text="Normal Text Label" FontSize="15" HorizontalOptions="CenterAndExpand" />
    <Label 
            FontSize="20" 
            FontAttributes="Bold"  
            Text="{Binding Text, Source={x:Reference InputEntry}}" />

    <Label Margin="0,10,0,0" BackgroundColor="Navy" TextColor="White" Text="Justified Text Label" FontSize="15" HorizontalOptions="CenterAndExpand" />
    <local:JustifiedLabel 
            FontSize="20" 
            FontAttributes="Bold" 
            Text="{Binding Text, Source={x:Reference InputEntry}}"
            TextColor="Green"
            BackgroundColor="Yellow"
            VerticalOptions="FillAndExpand"
            HorizontalOptions="FillAndExpand" />

</StackLayout>

enter image description here enter image description here

21
Sharada Gururaj 14 Сен 2017 в 21:41

Я никогда не видел простого решения для этого, только обходные пути, такие как упомянутые здесь.

Вам необходимо использовать компонент или создать собственное решение для каждой платформы.

0
Diego Rafael Souza 13 Сен 2017 в 16:39

Я думаю, что вы можете попробовать с

HorizontalOptions=LayoutOptions.FillAndExpand

HorizontalOptions

3
Alessandro Caliaro 1 Сен 2017 в 08:17

Я удивлен, что никто еще не поднял это ...

Очень простой способ добиться того же эффекта - заключить метку в собственный StackLayout, как показано ниже:

<StackLayout  Orientation="Vertical" >
    <Label Text="My Label" />
</StackLayout>
0
Jahmic 16 Авг 2019 в 18:20