Ответ 1
Немного сложно реализовать метку с поддержкой выравнивания выравнивания, но это возможно с помощью рендеринга (-ов) платформы.
Первым шагом будет объявление пользовательского элемента управления в проекте forms.
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 немного сложнее - поскольку андроид не поддерживает выравнивание выравнивания для 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> </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>