xamarin - modal - ¿Hay alguna manera de hacer que una etiqueta llene el espacio de izquierda a derecha?
xamarin forms navigation (3)
Aquí está el código que tengo:
<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>
La primera etiqueta de varias líneas comienza a la izquierda pero tiene espacios en algunas de las filas de la derecha. La 2ª y 3ª etiquetas multilínea están centradas y tienen espacios tanto a la izquierda como a la derecha.
¿Hay alguna manera de que todas las filas de las etiquetas llenen completamente las filas de izquierda a derecha o que el primer carácter de cada fila siempre se alinee a la izquierda y el último carácter de la última palabra de cada fila siempre líneas arriba a la derecha? Tenga en cuenta que esto requeriría que algunas palabras en cada línea tengan diferentes espacios entre ellas.
Es un poco complicado implementar la etiqueta con soporte de alineación justificada, pero es posible a través de los renderizadores de plataforma.
El primer paso sería declarar un control personalizado en el proyecto de formularios.
public class JustifiedLabel : Label { }
El siguiente paso es definir y registrar el renderizador de plataforma en iOS. Este es simple, ya que simplemente combinamos una cadena formateada con un estilo de párrafo para obtener lo que queremos.
[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;
}
}
}
En la plataforma Android, es un poco más complicado, ya que Android no admite la alineación justificada para TextView
, por lo que necesitaremos usar un WebView
lugar de hacerlo para representar el texto.
( Nota: también puede usar una biblioteca de Android y usarla en lugar de 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;
}
}
}
Uso de la muestra
<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>
Nunca vi una solución simple para esto, solo soluciones como las que se mencionan here .
Necesita usar un componente o crear su propia solución para cada plataforma.