【问题标题】:Set the font line height of a Xamarin.Forms Label设置 Xamarin.Forms 标签的字体行高
【发布时间】:2015-04-01 16:02:12
【问题描述】:

我有一个显示多行文本的 Xamarin.Forms 标签,我想增加行高以使文本更具可读性。

LabelSpan 控件上可用的字体属性似乎仅限于字体、大小和样式。

如何更改行高?

【问题讨论】:

    标签: c# xamarin.forms


    【解决方案1】:

    我能够通过定义如下的自定义渲染器来使其工作。首先,在您的 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
    }
    

    【讨论】:

      【解决方案2】:

      您需要一个自定义控件和渲染器,它可以从现有控件继承并处理其他属性。至于 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;
      

      【讨论】:

      • 我正在尝试这个,但我收到((UILabel)base.Control).Font.LineHeight = ((CustomLabel)this.Element).LineHeight; 行的错误,说“属性或索引器'UIFont.LineHeight' 不能分配给--它是只读的”
      【解决方案3】:

      我尝试了上述解决方案但没有成功。 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();
                  }
              }
          }
      }
      

      希望有效果

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-17
        • 2021-10-04
        • 2020-03-24
        • 2016-10-19
        • 2019-01-15
        • 1970-01-01
        • 2017-11-23
        • 1970-01-01
        相关资源
        最近更新 更多