簡體   English   中英

設置 Xamarin.Forms 標簽的字體行高

[英]Set the font line height of a Xamarin.Forms Label

我有一個 Xamarin.Forms 標簽顯示多行文本,我想增加行高以使文本更具可讀性。

LabelSpan控件上可用的字體屬性似乎僅限於字體、大小和樣式。

如何更改行高?

我能夠通過定義如下所示的自定義渲染器來使其工作。 首先,在您的 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
}

您將需要一個自定義控件和渲染,它可以從現有控件繼承並處理其他屬性。 至於iOS(關於Android的idk),你可以使用

// 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 而言(如果 Android 具有該功能,則為 idk)您還可以使用 UILabel 的UIAppearance來增加整個應用程序的行高,具體如下:

UILabel.Appearance.Font.LineHeight = 20f;

我嘗試了上述解決方案但沒有成功。 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

最后,AndroidRenderer:

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

希望它有效

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM