【问题标题】:How to control the line spacing in UILabelUILabel中如何控制行距
【发布时间】:2011-07-26 13:19:08
【问题描述】:

UILabel 中放入多行时,是否可以减少文本之间的间隙?我们可以设置框架、字体大小和行数。我想缩小该标签中两行之间的差距。

【问题讨论】:

标签: objective-c swift xcode uilabel line-spacing


【解决方案1】:

在 Xcode 6 中,您可以在情节提要中执行此操作:

【讨论】:

  • 充分利用情节提要!
  • @PaperThick 在 6.1.1 中有同样的问题。它“哈林摇晃”了几分钟。不知道如何解决:) Xcode Shaking
  • 有没有办法以这种方式设置自定义字体?我似乎无法将 helvetica neue 更改为任何其他字体。
  • 如果启用“Attributed”,然后将文件作为源代码打开,您可以手动编辑“lineHeightMultiple”,从而绕过 Harlem Shake 错误
  • @azdev 对于仍在关注此问题的任何人,我在 Xcode 7.3 中的震动时间更长,但我认为这是第一个没有问题的版本
【解决方案2】:

我想在这个答案中添加一些新的东西,所以我感觉没有那么糟糕......这是一个 Swift 答案:

import Cocoa

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 40

let attrString = NSMutableAttributedString(string: "Swift Answer")
attrString.addAttribute(.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attrString.length))

var tableViewCell = NSTableCellView()
tableViewCell.textField.attributedStringValue = attrString

“简短的回答:你不能。要更改文本行之间的间距,你必须继承 UILabel 并滚动你自己的 drawTextInRect,或者创建多个标签。”

见:Set UILabel line spacing


这是一个非常古老的答案,其他人已经添加了新的更好的方法来处理这个问题。请参阅下面提供的最新答案。

【讨论】:

  • 从iOS 6.0开始,您可以通过NSAttributedString来控制它(也可以在Xcode的界面构建器的UILable的属性中使用)。
  • 有趣的是,据我所知,您可以在行之间添加额外的间距,但在使用NSAttributedString 时不能通过NSParagraphStyle 减少它。 (我可能需要对其他可修改属性进行更多测试,但lineSpacing 属性只允许您增加它。)
  • 查看my answer 了解使用 NSAttributedString 的方法
  • @livingtech 这真令人气愤,我相信你是对的。您找到任何解决方法了吗?
  • 只是为了澄清这个线程中的一些内容。如果要缩小行距,请将行高设置为 1.0,然后将 setLineHeightMultiple 设置为
【解决方案3】:

从 iOS 6 开始,您可以为 UILabel 设置属性字符串。检查以下内容:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:label.text];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = spacing;
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, label.text.length)];

label.attributedText = attributedString;

【讨论】:

  • attributedString 必须是 NSMutableAttributedString(不是 NSAttributedString)
  • 第一行代码应该是NSMutableAttributedString *attributedString = [NSMutableAttributedString alloc]initWithString:@"sample text"];
  • NSMutableParagraphStylelineSpacing 属性永远不会是负数,因此无法使用这种方法降低行高。要回答这个问题,您必须使用另一个属性,请参阅@d.ennis 答案。
【解决方案4】:

此处所述的解决方案对我不起作用。我发现使用 iOS 6 NSAttributeString 的方法略有不同:

myLabel.numberOfLines = 0; 
NSString* string = @"String with line one. \n Line two. \n Line three.";
NSMutableParagraphStyle *style  = [[NSMutableParagraphStyle alloc] init];
style.minimumLineHeight = 30.f;
style.maximumLineHeight = 30.f;
NSDictionary *attributtes = @{NSParagraphStyleAttributeName : style,};
myLabel.attributedText = [[NSAttributedString alloc] initWithString:string
                                                         attributes:attributtes];   
[myLabel sizeToFit];

【讨论】:

  • 行高取决于字体大小。行距就是这样,行距。您可以通过设置最小/最大行高来解决问题,但这只是因为您使用的当前字体大小不大于行高边界。根据文档:“...超过此高度的字形和图形将与相邻行重叠...虽然此限制适用于行本身,但行间距会在相邻行之间增加额外的空间。”
  • +1,如果你想减少行间距,这就是你想要做的。默认情况下,实际行距很可能为 0,这就是为什么人们报告您只能增加它的原因。间距太大的问题来自于行高太大,这就是为什么这将在 99% 的时间内完成工作。
  • 这是我能找到的唯一答案,它使用 Photoshop、Sketch、CSS 等设计应用程序常见的实际行高值(而不是比率)。
【解决方案5】:

来自 Interface Builder(Storyboard/XIB):

以编程方式:

斯威夫特 4

使用标签扩展

extension UILabel {

    // Pass value for any one of both parameters and see result
    func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {

        guard let labelText = self.text else { return }

        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = lineSpacing
        paragraphStyle.lineHeightMultiple = lineHeightMultiple

        let attributedString:NSMutableAttributedString
        if let labelattributedText = self.attributedText {
            attributedString = NSMutableAttributedString(attributedString: labelattributedText)
        } else {
            attributedString = NSMutableAttributedString(string: labelText)
        }

        // Line spacing attribute
        attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))

        self.attributedText = attributedString
    }
}

现在调用分机功能

let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"

// Pass value for any one argument - lineSpacing or lineHeightMultiple
label.setLineSpacing(lineSpacing: 2.0) .  // try values 1.0 to 5.0

// or try lineHeightMultiple
//label.setLineSpacing(lineHeightMultiple = 2.0) // try values 0.5 to 2.0

或使用标签实例(只需复制并执行此代码即可查看结果)

let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40

// Line spacing attribute
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count))

// Character spacing attribute
attrString.addAttribute(NSAttributedStringKey.kern, value: 2, range: NSMakeRange(0, attrString.length))

label.attributedText = attrString

斯威夫特 3

let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
attrString.addAttribute(NSParagraphStyleAttributeName, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
label.attributedText = attrString

【讨论】:

  • 添加行“paragraphStyle.alignment = self.textAlignment”以保持原始对齐。否则,文本将左对齐。
  • 对于任何在大文本上丢失省略号的人,然后使用:paragraphStyle.lineBreakMode = .byTruncatingTail
【解决方案6】:

我制作了这个简单的扩展,非常适合我:

extension UILabel {
    func setLineHeight(lineHeight: CGFloat) {
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = 1.0
        paragraphStyle.lineHeightMultiple = lineHeight
        paragraphStyle.alignment = self.textAlignment

        let attrString = NSMutableAttributedString()
        if (self.attributedText != nil) {
            attrString.append( self.attributedText!)
        } else {
            attrString.append( NSMutableAttributedString(string: self.text!))
            attrString.addAttribute(NSAttributedStringKey.font, value: self.font, range: NSMakeRange(0, attrString.length))
        }
        attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attrString.length))
        self.attributedText = attrString
    }
}

把它复制到一个文件中,这样你就可以像这样使用它了

myLabel.setLineHeight(0.7)

【讨论】:

  • 请记住,如果您在为此标签使用 Storyboard 的同时执行此操作,请务必将标签的行数设置为 0
  • 你为什么不直接设置lineSpacing而忘记设置lineHeightMultiple
  • 因为减小行高的关键是'lineHeightMultiple',所以没有lineSpacing
  • 说你希望你的行高为 1.4,为什么你不能只写.lineSpacing = 1.4 而忘记所有关于.lineHeightMultiple...
  • 哈!我试过了,但我没有工作,但我想知道为什么我没有使用你的机制在这里看不到其他答案,我的意思是他们只是直接设置了 lineSpacing。查看接受的答案...
【解决方案7】:

现在在 iOS 6 中有一个替代答案,即在标签上设置属性文本,使用具有适当段落样式的 NSAttributedString。有关使用 NSAttributedString 的行高的详细信息,请参阅此堆栈溢出答案:

Core Text - NSAttributedString line height done right?

【讨论】:

    【解决方案8】:

    这是一个继承 UILabel 以具有 line-height 属性的类:https://github.com/LemonCake/MSLabel

    【讨论】:

    • 这对我有用,谢谢。我也尝试使用 MTLabel,但这个更好。
    • 有谁知道MSLabel是否支持'\n'字符?
    【解决方案9】:

    在 Swift 中作为函数,受 DarkDust 启发

    // Usage: setTextWithLineSpacing(myEpicUILabel,text:"Hello",lineSpacing:20)
    func setTextWithLineSpacing(label:UILabel,text:String,lineSpacing:CGFloat)
    {
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = lineSpacing
    
        let attrString = NSMutableAttributedString(string: text)
        attrString.addAttribute(NSAttributedString.Key.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attrString.length))
    
        label.attributedText = attrString
    }
    

    【讨论】:

      【解决方案10】:

      根据@Mike 的回答,减少lineHeightMultiple 是关键点。下面的例子,它对我很有效:

      NSString* text = label.text;
      CGFloat textWidth = [text sizeWithAttributes:@{NSFontAttributeName: label.font}].width;
      if (textWidth > label.frame.size.width) {
        NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
        paragraph.alignment = NSTextAlignmentCenter;
        paragraph.lineSpacing = 1.0f;
        paragraph.lineHeightMultiple = 0.75;     // Reduce this value !!!
        NSMutableAttributedString* attrText = [[NSMutableAttributedString alloc] initWithString:text];
        [attrText addAttribute:NSParagraphStyleAttributeName value:paragraph range:NSMakeRange(0, text.length)];
        label.attributedText = attrText;
      }
      

      【讨论】:

        【解决方案11】:

        SWIFT 3 用于更轻松地设置行间距的有用扩展 :)

        extension UILabel
        {
            func setLineHeight(lineHeight: CGFloat)
            {
                let text = self.text
                if let text = text 
                {
        
                    let attributeString = NSMutableAttributedString(string: text)
                    let style = NSMutableParagraphStyle()
        
                   style.lineSpacing = lineHeight
                   attributeString.addAttribute(NSParagraphStyleAttributeName,
                                                value: style,
                                                range: NSMakeRange(0, text.characters.count))
        
                   self.attributedText = attributeString
                }
            }
        }
        

        【讨论】:

          【解决方案12】:

          我找到了一种方法,您可以设置实际行高(不是一个因素),它甚至可以在界面生成器中实时呈现。只需按照以下说明进行操作。代码是用 Swift 4 编写的。


          步骤#1:创建一个名为DesignableLabel.swift的文件并插入以下代码:

          import UIKit
          
          @IBDesignable
          class DesignableLabel: UILabel {
              @IBInspectable var lineHeight: CGFloat = 20 {
                  didSet {
                      let paragraphStyle = NSMutableParagraphStyle()
                      paragraphStyle.minimumLineHeight = lineHeight
                      paragraphStyle.maximumLineHeight = lineHeight
                      paragraphStyle.alignment = self.textAlignment
          
                      let attrString = NSMutableAttributedString(string: text!)
                      attrString.addAttribute(NSAttributedStringKey.font, value: font, range: NSRange(location: 0, length: attrString.length))
                      attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attrString.length))
                      attributedText = attrString
                  }
              }
          }
          

          步骤#2:UILabel 放入Storyboard/XIB 并将其类设置为DesignableLabel。等待您的项目构建(构建必须成功!)。


          第 3 步:现在您应该会在属性窗格中看到一个名为“Line Height”的新属性。只需设置您喜欢的值,您应该立即看到结果!

          【讨论】:

            【解决方案13】:

            这是 UILabel 的一个子类,它设置 lineHeightMultiple 并确保固有高度足够大而不会截断文本。

            @IBDesignable
            class Label: UILabel {
                override var intrinsicContentSize: CGSize {
                    var size = super.intrinsicContentSize
                    let padding = (1.0 - lineHeightMultiple) * font.pointSize
                    size.height += padding
                    return size
                }
            
                override var text: String? {
                    didSet {
                        updateAttributedText()
                    }
                }
            
                @IBInspectable var lineHeightMultiple: CGFloat = 1.0 {
                    didSet {
                        updateAttributedText()
                    }
                }
            
                private func updateAttributedText() {
                    let paragraphStyle = NSMutableParagraphStyle()
                    paragraphStyle.lineHeightMultiple = lineHeightMultiple
                    attributedText = NSAttributedString(string: text ?? "", attributes: [
                        .font: font,
                        .paragraphStyle: paragraphStyle,
                        .foregroundColor: textColor
                    ])
                    invalidateIntrinsicContentSize()
                }
            }
            

            【讨论】:

            • 额外的填充必须是 (lineHeightMultiple - 1.0) * font.pointSize,对吧?
            • 上面的代码似乎对我有用。但也许你是对的。你试过你的改变吗? @PavelAlexeev
            • 不,我坚持使用 lineSpacing 而不是 lineHeightMultiple :)
            【解决方案14】:

            在 Swift 2.0 中...

            添加扩展:

            extension UIView {
                func attributesWithLineHeight(font: String, color: UIColor, fontSize: CGFloat, kern: Double, lineHeightMultiple: CGFloat) -> [String: NSObject] {
                    let titleParagraphStyle = NSMutableParagraphStyle()
                    titleParagraphStyle.lineHeightMultiple = lineHeightMultiple
            
                    let attribute = [
                        NSForegroundColorAttributeName: color,
                        NSKernAttributeName: kern,
                        NSFontAttributeName : UIFont(name: font, size: fontSize)!,
                        NSParagraphStyleAttributeName: titleParagraphStyle
                    ]
                    return attribute
                }
            }
            

            现在,只需将您的 UILabel 设置为属性文本:

            self.label.attributedText = NSMutableAttributedString(string: "SwiftExample", attributes: attributesWithLineHeight("SourceSans-Regular", color: UIColor.whiteColor(), fontSize: 20, kern: 2.0, lineHeightMultiple: 0.5))    
            

            显然,我添加了一堆您可能不需要的参数。玩转——随意重写方法——我在一堆不同的答案上寻找这个,所以我想我会发布整个扩展,以防它帮助那里的人......-rab

            【讨论】:

              【解决方案15】:

              Swift3 - 在 UITextView 或 UILabel 扩展中,添加这个函数:

              如果您已经在视图中使用属性字符串(而不是覆盖它们),我添加了一些代码来保留当前属性文本。

              func setLineHeight(_ lineHeight: CGFloat) {
                  guard let text = self.text, let font = self.font else { return }
              
                  let paragraphStyle = NSMutableParagraphStyle()
                  paragraphStyle.lineSpacing = 1.0
                  paragraphStyle.lineHeightMultiple = lineHeight
                  paragraphStyle.alignment = self.textAlignment
              
                  var attrString:NSMutableAttributedString
                  if let attributed = self.attributedText {
                      attrString = NSMutableAttributedString(attributedString: attributed)
                  } else {
                      attrString = NSMutableAttributedString(string: text)
                      attrString.addAttribute(NSFontAttributeName, value: font, range: NSMakeRange(0, attrString.length))
                  }
                  attrString.addAttribute(NSParagraphStyleAttributeName, value:paragraphStyle, range:NSMakeRange(0, attrString.length))
                  self.attributedText = attrString
              }
              

              【讨论】:

                【解决方案16】:

                另一个答案...如果您以编程方式传递字符串,则需要传递属性字符串而不是常规字符串并更改其样式。(iOS10)

                NSMutableAttributedString * attrString = [[NSMutableAttributedString alloc] initWithString:@"Your \nregular \nstring"];
                NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
                [style setLineSpacing:4];
                [attrString addAttribute:NSParagraphStyleAttributeName
                                   value:style
                                   range:NSMakeRange(0, attrString.length)];
                _label.attributedText = attrString;
                

                【讨论】:

                  【解决方案17】:

                  这应该会有所帮助。然后,您可以将标签分配给情节提要中的这个自定义类,并直接在属性中使用它的参数:

                  open class SpacingLabel : UILabel {
                  
                      @IBInspectable open var lineHeight:CGFloat = 1 {
                          didSet {
                              let paragraphStyle = NSMutableParagraphStyle()
                              paragraphStyle.lineSpacing = 1.0
                              paragraphStyle.lineHeightMultiple = self.lineHeight
                              paragraphStyle.alignment = self.textAlignment
                  
                              let attrString = NSMutableAttributedString(string: self.text!)
                              attrString.addAttribute(NSAttributedStringKey.font, value: self.font, range: NSMakeRange(0, attrString.length))
                              attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attrString.length))
                              self.attributedText = attrString
                          }
                      } 
                  }
                  

                  【讨论】:

                  • 这应该会有所帮助。然后,您可以将标签分配给情节提要中的此自定义类,并直接在属性中使用它的参数。
                  • 请不要将与您的答案相关的内容放在 cmets 中。您的答案应该会有所帮助,而无需通读 cmets
                  【解决方案18】:

                  Swift 4 标签扩展。在传递给函数之前创建 NSMutableAttributedString,以防属性文本需要额外的属性。

                  extension UILabel {
                  
                      func setLineHeightMultiple(to height: CGFloat, withAttributedText attributedText: NSMutableAttributedString) {
                  
                          let paragraphStyle = NSMutableParagraphStyle()
                          paragraphStyle.lineSpacing = 1.0
                          paragraphStyle.lineHeightMultiple = height
                          paragraphStyle.alignment = textAlignment
                  
                          attributedText.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedText.length - 1))
                  
                          self.attributedText = attributedText
                      }
                  }
                  

                  【讨论】:

                    【解决方案19】:

                    Swift 3 扩展:

                    import UIKit
                        
                    extension UILabel {
                      func setTextWithLineSpacing(text: String, lineHeightMultiply: CGFloat = 1.3) {
                        let paragraphStyle = NSMutableParagraphStyle()
                        paragraphStyle.lineHeightMultiple = lineHeightMultiply
                        paragraphStyle.alignment = .center
                        let attributedString = NSMutableAttributedString(string: text)
                        attributedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length))
                        self.attributedText = attributedString
                      }
                    }
                    

                    【讨论】:

                      【解决方案20】:

                      这段代码对我有用(肯定是 ios 7 和 ios 8)。

                      _label.numberOfLines=2;
                      _label.textColor=[UIColor whiteColor];
                      
                      NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
                      paragraphStyle.lineHeightMultiple=0.5;
                      paragraphStyle.alignment = NSTextAlignmentCenter;
                      paragraphStyle.lineSpacing = 1.0;
                      
                      NSDictionary *nameAttributes=@{
                                                     NSParagraphStyleAttributeName : paragraphStyle,
                                                     NSBaselineOffsetAttributeName:@2.0
                                                     };
                      
                      
                      NSAttributedString *string=[[NSAttributedString alloc] initWithString:@"22m\nago" attributes:nameAttributes];
                      _label.attributedText=string;
                      

                      【讨论】:

                        【解决方案21】:

                        这是我的快速解决方案。子类应该适用于属性文本和文本属性以及 characterSpacing + lineSpacing。如果设置了新字符串或属性字符串,它会保留间距。

                        open class UHBCustomLabel : UILabel {
                            @IBInspectable open var characterSpacing:CGFloat = 1 {
                                didSet {
                                    updateWithSpacing()
                                }
                        
                            }
                            @IBInspectable open var lines_spacing:CGFloat = -1 {
                                didSet {
                                    updateWithSpacing()
                                }
                        
                            }
                            open override var text: String? {
                                set {
                                    super.text = newValue
                                    updateWithSpacing()
                                }
                                get {
                                    return super.text
                                }
                            }
                            open override var attributedText: NSAttributedString? {
                                set {
                                    super.attributedText = newValue
                                    updateWithSpacing() 
                                }
                                get {
                                    return super.attributedText
                                }
                            }
                            func updateWithSpacing() {
                                let attributedString = self.attributedText == nil ? NSMutableAttributedString(string: self.text ?? "") : NSMutableAttributedString(attributedString: attributedText!)
                                attributedString.addAttribute(NSKernAttributeName, value: self.characterSpacing, range: NSRange(location: 0, length: attributedString.length))
                                if lines_spacing >= 0 {
                                    let paragraphStyle = NSMutableParagraphStyle()
                                    paragraphStyle.lineSpacing = lines_spacing
                                    paragraphStyle.alignment = textAlignment
                                    attributedString.addAttribute(NSParagraphStyleAttributeName, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))
                                }
                                super.attributedText = attributedString
                            }
                        }
                        

                        【讨论】:

                          【解决方案22】:

                          作为一种快速而简单的解决方法:

                          对于没有太多行的 UILabel,您可以改用 stackViews。

                          1. 为每一行写一个新标签。
                          2. 将它们嵌入 StackView。(选择两个标签-->Editor-->嵌入-->StackView
                          3. 将 StackView 的 Spacing 调整为您想要的数量

                          请务必将它们垂直堆叠起来。 此解决方案也适用于自定义字体。

                          【讨论】:

                          • FWIW 这是一个糟糕但可行的解决方案。因此我保留了它。
                          • 我还看到 iOS 开发人员使用堆栈视图创建图表的原则。 Stackviews 非常强大
                          猜你喜欢
                          • 1970-01-01
                          • 2015-08-03
                          • 2013-01-11
                          • 1970-01-01
                          • 2017-01-02
                          • 2011-04-22
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多