设置Xamarin.Forms标签的字体行高
Set the font line height of a Xamarin.Forms Label
我有一个显示多行文本的 Xamarin.Forms 标签,我想增加行高以使文本更易读。
Label
和 Span
控件上可用的字体属性似乎仅限于字体、大小和样式。
如何更改行高?
您需要一个自定义控件和呈现器,它可以继承现有控件并处理其他属性。至于 iOS(我知道 Android)你可以使用
// this goes in the Forms project
public class CustomLabel : Label{
// make it bindable, shortened for simplicity here
public double LineHeight {get;set;}
}
// this goes in the iOS project, another one in the Android project
// notice the attribute is before the namespace
[assembly: ExportRendererAttribute (typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace MyNamespace{
public class CustomLabelRenderer: LabelRenderer
protected override void OnElementChanged (ElementChangedEventArgs<Frame> e){
base.OnElementChanged(e);
// sample only; expand, validate and handle edge cases as needed
((UILabel)base.Control).Font.LineHeight = ((CustomLabel)this.Element).LineHeight;
}
// if your property is bindable you can handle changes in this method:
// protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
}
至于 iOS(idk 如果 Android 具有该功能)您还可以使用 UILabel 的 UIAppearance 来增加整个应用程序的行高,行中的内容的:
UILabel.Appearance.Font.LineHeight = 20f;
我能够通过如下定义自定义渲染器来使其工作。首先,在您的 Forms 项目 (PCL) 中,定义一个自定义标签并添加一个 LineHeight 属性:
// Put this your forms project
public class CustomLabel : Label
{
public double LineHeight { get; set; }
}
然后,在您的 iOS 项目中,您可以这样定义渲染器:
// Put this in your iOS project
[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace MyNamespace
{
public class CustomLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
// Make sure control is not null
var label = (CustomLabel)Element;
if (label == null || Control == null)
{
return;
}
var labelString = new NSMutableAttributedString(label.Text);
var paragraphStyle = new NSMutableParagraphStyle { LineSpacing = (nfloat)label.LineHeight };
var style = UIStringAttributeKey.ParagraphStyle;
var range = new NSRange(0, labelString.Length);
labelString.AddAttribute(style, paragraphStyle, range);
Control.AttributedText = labelString;
}
}
}
最后,您可以像这样在您的页面上使用它:
new Label {
Text = "some text",
LineHeight = 20
}
我尝试了上述解决方案,但没有成功。 Android 和 iOS 中的行为不同,因此我研究了一个类似的解决方案,在两个平台上实现了相同的行为。
// Put this your forms project
public class CustomLabel : Label
{
public static readonly BindableProperty LineHeightProperty =
BindableProperty.Create("LineHeight", typeof(double), typeof(CustomLabel));
public double LineHeight
{
get { return (double)GetValue(LineHeightProperty); }
set { SetValue(LineHeightProperty, value); }
}
}
然后,iOS 渲染器:
// Put this in your iOS project
[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace App.iOS.Components
{
public class CustomLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
var label = (CustomLabel)Element;
if (label == null || Control == null)
{
return;
}
double fontSize = label.FontSize;
//iOS LineSpacing is measured in dp, as the FontSize. So, if we need a LineSpacing of 2,
//this LineSpacing must be set to the same value of the FontSize
nfloat lineSpacing = ((nfloat)label.LineHeight * (nfloat)fontSize) - (nfloat)fontSize;
if (lineSpacing > 0)
{
var labelString = new NSMutableAttributedString(label.Text);
var paragraphStyle = new NSMutableParagraphStyle { LineSpacing = lineSpacing };
var style = UIStringAttributeKey.ParagraphStyle;
var range = new NSRange(0, labelString.Length);
labelString.AddAttribute(style, paragraphStyle, range);
Control.AttributedText = labelString;
}
}
}
}
请注意,在 iOS 中,LineSpacing 属性 不同于 Android:
Android 中的 LineSpacing = 2
等同于 iOS
中的 LineSpacing = FontSize
最后,Android渲染器:
// Put this in your Android project
[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace App.Droid.Components
{
public class CustomLabelRenderer : LabelRenderer
{
protected CustomLabel CustomLabel { get; private set; }
public CustomLabelRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
this.CustomLabel = (CustomLabel)this.Element;
}
double lineSpacing = this.CustomLabel.LineHeight;
if (lineSpacing > 0)
{
this.Control.SetLineSpacing(1f, (float)lineSpacing);
this.UpdateLayout();
}
}
}
}
希望有用
我有一个显示多行文本的 Xamarin.Forms 标签,我想增加行高以使文本更易读。
Label
和 Span
控件上可用的字体属性似乎仅限于字体、大小和样式。
如何更改行高?
您需要一个自定义控件和呈现器,它可以继承现有控件并处理其他属性。至于 iOS(我知道 Android)你可以使用
// this goes in the Forms project
public class CustomLabel : Label{
// make it bindable, shortened for simplicity here
public double LineHeight {get;set;}
}
// this goes in the iOS project, another one in the Android project
// notice the attribute is before the namespace
[assembly: ExportRendererAttribute (typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace MyNamespace{
public class CustomLabelRenderer: LabelRenderer
protected override void OnElementChanged (ElementChangedEventArgs<Frame> e){
base.OnElementChanged(e);
// sample only; expand, validate and handle edge cases as needed
((UILabel)base.Control).Font.LineHeight = ((CustomLabel)this.Element).LineHeight;
}
// if your property is bindable you can handle changes in this method:
// protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
}
至于 iOS(idk 如果 Android 具有该功能)您还可以使用 UILabel 的 UIAppearance 来增加整个应用程序的行高,行中的内容的:
UILabel.Appearance.Font.LineHeight = 20f;
我能够通过如下定义自定义渲染器来使其工作。首先,在您的 Forms 项目 (PCL) 中,定义一个自定义标签并添加一个 LineHeight 属性:
// Put this your forms project
public class CustomLabel : Label
{
public double LineHeight { get; set; }
}
然后,在您的 iOS 项目中,您可以这样定义渲染器:
// Put this in your iOS project
[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace MyNamespace
{
public class CustomLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
// Make sure control is not null
var label = (CustomLabel)Element;
if (label == null || Control == null)
{
return;
}
var labelString = new NSMutableAttributedString(label.Text);
var paragraphStyle = new NSMutableParagraphStyle { LineSpacing = (nfloat)label.LineHeight };
var style = UIStringAttributeKey.ParagraphStyle;
var range = new NSRange(0, labelString.Length);
labelString.AddAttribute(style, paragraphStyle, range);
Control.AttributedText = labelString;
}
}
}
最后,您可以像这样在您的页面上使用它:
new Label {
Text = "some text",
LineHeight = 20
}
我尝试了上述解决方案,但没有成功。 Android 和 iOS 中的行为不同,因此我研究了一个类似的解决方案,在两个平台上实现了相同的行为。
// Put this your forms project
public class CustomLabel : Label
{
public static readonly BindableProperty LineHeightProperty =
BindableProperty.Create("LineHeight", typeof(double), typeof(CustomLabel));
public double LineHeight
{
get { return (double)GetValue(LineHeightProperty); }
set { SetValue(LineHeightProperty, value); }
}
}
然后,iOS 渲染器:
// Put this in your iOS project
[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace App.iOS.Components
{
public class CustomLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
var label = (CustomLabel)Element;
if (label == null || Control == null)
{
return;
}
double fontSize = label.FontSize;
//iOS LineSpacing is measured in dp, as the FontSize. So, if we need a LineSpacing of 2,
//this LineSpacing must be set to the same value of the FontSize
nfloat lineSpacing = ((nfloat)label.LineHeight * (nfloat)fontSize) - (nfloat)fontSize;
if (lineSpacing > 0)
{
var labelString = new NSMutableAttributedString(label.Text);
var paragraphStyle = new NSMutableParagraphStyle { LineSpacing = lineSpacing };
var style = UIStringAttributeKey.ParagraphStyle;
var range = new NSRange(0, labelString.Length);
labelString.AddAttribute(style, paragraphStyle, range);
Control.AttributedText = labelString;
}
}
}
}
请注意,在 iOS 中,LineSpacing 属性 不同于 Android:
Android 中的 LineSpacing = 2
等同于 iOS
LineSpacing = FontSize
最后,Android渲染器:
// Put this in your Android project
[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace App.Droid.Components
{
public class CustomLabelRenderer : LabelRenderer
{
protected CustomLabel CustomLabel { get; private set; }
public CustomLabelRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
this.CustomLabel = (CustomLabel)this.Element;
}
double lineSpacing = this.CustomLabel.LineHeight;
if (lineSpacing > 0)
{
this.Control.SetLineSpacing(1f, (float)lineSpacing);
this.UpdateLayout();
}
}
}
}
希望有用