简体   繁体   中英

How to Increase Line spacing in UILabel in Swift

I have a label which has few lines of text and I want to increase the spacing between the lines. There are similar questions asked by others but the solutions don't solve my problems. Also my label may or may not contain paragraphs. I am new to Swift . Is there a solution using storyboard? Or only through NSAttributedString its possible?

Programatically add LineSpacing to your UILabel using following snippet.

Earlier Swift version

let attributedString = NSMutableAttributedString(string: "Your text")

// *** Create instance of `NSMutableParagraphStyle`
let paragraphStyle = NSMutableParagraphStyle()

// *** set LineSpacing property in points ***
paragraphStyle.lineSpacing = 2 // Whatever line spacing you want in points

// *** Apply attribute to string ***
attributedString.addAttribute(NSParagraphStyleAttributeName, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))

// *** Set Attributed String to your label ***
label.attributedText = attributedString

Swift 4.0

let attributedString = NSMutableAttributedString(string: "Your text")

// *** Create instance of `NSMutableParagraphStyle`
let paragraphStyle = NSMutableParagraphStyle()

// *** set LineSpacing property in points ***
paragraphStyle.lineSpacing = 2 // Whatever line spacing you want in points

// *** Apply attribute to string ***
attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))

// *** Set Attributed String to your label ***
label.attributedText = attributedString

Swift 4.2

let attributedString = NSMutableAttributedString(string: "Your text")

// *** Create instance of `NSMutableParagraphStyle`
let paragraphStyle = NSMutableParagraphStyle()

// *** set LineSpacing property in points ***
paragraphStyle.lineSpacing = 2 // Whatever line spacing you want in points

// *** Apply attribute to string ***
attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))

// *** Set Attributed String to your label ***
label.attributedText = attributedString

From Interface Builder:

在此处输入图片说明

Programmatically:

SWift 4 & 4.2

Using label extension

extension UILabel {

    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)
        }

        // (Swift 4.2 and above) Line spacing attribute
        attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))


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

        self.attributedText = attributedString
    }
}

Now call extension function

let label = UILabel()
let stringValue = "Set\nUILabel\nline\nspacing"

// 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

Or using label instance (Just copy & execute this code to see result)

let label = UILabel()
let stringValue = "Set\nUILabel\nline\nspacing"
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

Swift 3

let label = UILabel()
let stringValue = "Set\nUILabel\nline\nspacing"
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

You can control the line spacing in storyboard .

在此处输入图片说明

Same question.

Recent solution for Swift 5.0

private extension UILabel {

    // MARK: - spacingValue is spacing that you need
    func addInterlineSpacing(spacingValue: CGFloat = 2) {

        // MARK: - Check if there's any text
        guard let textString = text else { return }

        // MARK: - Create "NSMutableAttributedString" with your text
        let attributedString = NSMutableAttributedString(string: textString)

        // MARK: - Create instance of "NSMutableParagraphStyle"
        let paragraphStyle = NSMutableParagraphStyle()

        // MARK: - Actually adding spacing we need to ParagraphStyle
        paragraphStyle.lineSpacing = spacingValue

        // MARK: - Adding ParagraphStyle to your attributed String
        attributedString.addAttribute(
            .paragraphStyle,
            value: paragraphStyle,
            range: NSRange(location: 0, length: attributedString.length
        ))

        // MARK: - Assign string that you've modified to current attributed Text
        attributedText = attributedString
    }

}

And the usage:

let yourLabel = UILabel()
let yourText = "Hello \n world \n !"
yourLabel.text = yourText
yourLabel.addInterlineSpacing(spacingValue: 1.5)

You can use this reusable extension:

extension String {

func lineSpaced(_ spacing: CGFloat) -> NSAttributedString {
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.lineSpacing = spacing
    let attributedString = NSAttributedString(string: self, attributes: [NSAttributedString.Key.paragraphStyle: paragraphStyle])
    return attributedString
}
}

Swift 4 and Swift 5

extension NSAttributedString {
    func withLineSpacing(_ spacing: CGFloat) -> NSAttributedString {


        let attributedString = NSMutableAttributedString(attributedString: self)
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineBreakMode = .byTruncatingTail
        paragraphStyle.lineSpacing = spacing
        attributedString.addAttribute(.paragraphStyle,
                                      value: paragraphStyle,
                                      range: NSRange(location: 0, length: string.count))
        return NSAttributedString(attributedString: attributedString)
    }
}

How to use

    let example = NSAttributedString(string: "This is Line 1 \nLine 2 \nLine 3 ").withLineSpacing(15)
    testLabel.attributedText = example

示例

Dipen's answer updated for Swift 4

let attr = NSMutableAttributedString(string: today)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 2
attr.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, attr.length))
label.attributedText = attr;
//Swift 4:
    func set(text:String,
                         inLabel:UILabel,
                         withLineSpacing:CGFloat,
                         alignment:NSTextAlignment){
            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.lineSpacing = withLineSpacing
            let attrString = NSMutableAttributedString(string: text)
            attrString.addAttribute(NSAttributedStringKey.paragraphStyle,
                                    value:paragraphStyle,
                                    range:NSMakeRange(0, attrString.length))
            inLabel.attributedText = attrString
            inLabel.textAlignment = alignment
          }
extension UILabel {
    var spasing:CGFloat {
        get {return 0}
        set {
            let textAlignment = self.textAlignment
            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.lineSpacing = newValue
            let attributedString = NSAttributedString(string: self.text ?? "", attributes: [NSAttributedString.Key.paragraphStyle: paragraphStyle])
            self.attributedText = attributedString
            self.textAlignment = textAlignment
        }
    }
}


let label = UILabel()
label.text = "test"
label.spasing = 10

In addition to using attributed strings & paragraph styles, for small adjustemnts, font descriptors can also come in handy.

For instance:

let font: UIFont = .init(
    descriptor: UIFontDescriptor
        .preferredFontDescriptor(withTextStyle: .body)
        .withSymbolicTraits(.traitLooseLeading)!,
    size: 0
)

This will create a font with a looser leading, resulting in a text with a slightly larger line height (it adds 2 points) than the default system font. traitTightLeading can also be used for the opposite effect (it reduces the leading of the font by 2 points).

I wrote a blog post comparing the approaches here: https://bootstragram.com/blog/line-height-with-uikit/ .

Create LabelStyle

struct LabelStyle {
    
        let font: UIFont
        let fontMetrics: UIFontMetrics?
        let lineHeight: CGFloat?
        let tracking: CGFloat
        
        init(font: UIFont, fontMetrics: UIFontMetrics? = nil, lineHeight: CGFloat? = nil, tracking: CGFloat = 0) {
            self.font = font
            self.fontMetrics = fontMetrics
            self.lineHeight = lineHeight
            self.tracking = tracking
        }
        
        func attributes(for alignment: NSTextAlignment, lineBreakMode: NSLineBreakMode) -> [NSAttributedString.Key: Any] {
            
            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.alignment = alignment
            paragraphStyle.lineBreakMode = lineBreakMode
            
            var baselineOffset: CGFloat = .zero
            
            if let lineHeight = lineHeight {
                let lineHeightMultiple = lineHeight / font.lineHeight
                paragraphStyle.lineHeightMultiple = lineHeightMultiple
                
                baselineOffset = 1 / lineHeightMultiple
                
                let scaledLineHeight: CGFloat = fontMetrics?.scaledValue(for: lineHeight) ?? lineHeight
                paragraphStyle.minimumLineHeight = scaledLineHeight
                paragraphStyle.maximumLineHeight = scaledLineHeight
            }
            
            return [
                NSAttributedString.Key.paragraphStyle: paragraphStyle,
                NSAttributedString.Key.kern: tracking,
                NSAttributedString.Key.baselineOffset: baselineOffset,
                NSAttributedString.Key.font: font
            ]
        }
    }

Create custom Label class and use our style

public class Label: UILabel {
  
  var style: LabelStyle? { nil }
  
  public override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    
    if previousTraitCollection?.preferredContentSizeCategory != traitCollection.preferredContentSizeCategory {
      updateText()
    }
  }
  
  convenience init(text: String?, textColor: UIColor) {
    self.init()
    self.text = text
    self.textColor = textColor
  }
  
  override init(frame: CGRect) {
    super.init(frame: frame)
    commonInit()
  }
  
  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    commonInit()
    updateText()
  }
  
  private func commonInit() {
    font = style?.font
    adjustsFontForContentSizeCategory = true
  }
  
  private func updateText() {
    text = super.text
  }
  
  public override var text: String? {
    get {
      guard style?.attributes != nil else {
        return super.text
      }
      
      return attributedText?.string
    }
    set {
      guard let style = style else {
        super.text = newValue
        return
      }
      
      guard let newText = newValue else {
        attributedText = nil
        super.text = nil
        return
      }
      
      let attributes = style.attributes(for: textAlignment, lineBreakMode: lineBreakMode)
      attributedText = NSAttributedString(string: newText, attributes: attributes)
    }
  }
}

Create concrete Label

public final class TitleLabel {

    override var style: LabelStyle? {
        LabelStyle(
            font: UIFont.Title(),
            lineHeight: 26.21,
            tracking: 0.14
        )
    }
}

and use it

@IBOutlet weak var titleLabel: TitleLabel!

This solution worked for swift 5 this is reference to answer of https://stackoverflow.com/a/62116213/13171606

I Made some changes for " NSMutableAttributedString " and included the full example, i think it will help u all

Note: Please Adjust Color and Font style if found any error.

Extension

extension NSAttributedString {
    func withLineSpacing(_ spacing: CGFloat) -> NSMutableAttributedString {
            let attributedString = NSMutableAttributedString(attributedString: self)
            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.lineBreakMode = .byTruncatingTail
            paragraphStyle.lineSpacing = spacing
            attributedString.addAttribute(.paragraphStyle,
                                  value: paragraphStyle,
                                  range: NSRange(location: 0, length: string.count))
            return NSMutableAttributedString(attributedString: attributedString)
    }
}

Implementation Example

let myAttributedText = NSMutableAttributedString(string: "Please enter the required details to change your AAAAAAAAA AAAAA AAAAA. Maximum AAAAA can be AAA AA AAA AA.\n\nNote: If you do not have a AAAAA AAAA then please AAAAAAA us at 111-111-111 or send us an email AAAA AAAA AAA AAAAAAAAAA AAAAA address at xxxxxxxxxxxxxxxxxxxxxxxxxxxx.", attributes: [
        .font: UIFont.systemFont(ofSize: 14),
        .foregroundColor: UIColor.gray,
        .kern: 0.0]).withLineSpacing(8)
    myAttributedText.addAttributes([
        .font: UIFont.systemFont(ofSize: 14),
        .foregroundColor: UIColor.blue],
                                   range: NSRange(location: 174, length: 11))
    myAttributedText.addAttributes([
        .font: UIFont.systemFont(ofSize: 14),
        .foregroundColor: UIColor.blue],
                                   range: NSRange(location: 248, length: 28))

UILable

let myLabel: UILabel = {
   let label = UILabel()
   label.textAlignment = .left
   label.numberOfLines = 0
   label.attributedText = myAttributedText //Here is your Attributed String
   return label
}() 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM