Core Text - NSAttributedString line height done right?

前端 未结 10 766
Happy的楠姐
Happy的楠姐 2020-12-23 09:21

I\'m completely in the dark with Core Text\'s line spacing. I\'m using NSAttributedString and I specify the following attributes on it: - kCTFontAttributeName - kCTParagraph

相关标签:
10条回答
  • 2020-12-23 09:35

    This worked for me in Xcode 7.2. iOS 9.2.1. (Swift 2.1.):

      dispatch_async(dispatch_get_main_queue()) { () -> Void in
            let paragraphStyleWithSpacing           = NSMutableParagraphStyle()
            paragraphStyleWithSpacing.lineSpacing   = 2.0 //CGFloat
            let textWithLineSpacing                 = NSAttributedString(string: str, attributes: [NSParagraphStyleAttributeName : paragraphStyleWithSpacing])
            self.MY_TEXT_VIEW_NAME.attributedText   = textWithLineSpacing
        }
    
    0 讨论(0)
  • 2020-12-23 09:36

    Swift 4 & 5

    extension NSAttributedString {
    
        /// Returns a new instance of NSAttributedString with same contents and attributes with line spacing added.
         /// - Parameter spacing: value for spacing you want to assign to the text.
         /// - Returns: a new instance of NSAttributedString with given line spacing.
         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)
         }
    }
    
    0 讨论(0)
  • 2020-12-23 09:45

    I tried all these answers, but to really get the EXACT line height that usually comes in design files from Sketch or Zeplin then you need to:

    let ps = NSMutableParagraphStyle()
    ps.minimumLineHeight = 34
    ps.maximumLineHeight = 34
    let attrText = NSAttributedString(
        string: "Your long multiline text that will have exact line height spacing",
        attributes: [
            .paragraphStyle: ps
        ]
    )
    someLabel.attributedText = attrText
    someLabel.numberOfLines = 2
    ...
    
    0 讨论(0)
  • 2020-12-23 09:46

    You can set/update line spacing and line height multiple from storyboard as well as programatically.

    From Interface Builder:

    enter image description here

    Programmatically:

    SWift 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
    
    // Swift 4.2++
    
    
    attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))
    
    // Swift 4.1--
    attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))
    
            self.attributedText = attributedString
        }
    }
    

    Now call extension function

    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
    

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

    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
    
    // Swift 4.2++
    // Line spacing attribute
    attrString.addAttribute(NSAttributedString.Key.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
    
    // Character spacing attribute
    attrString.addAttribute(NSAttributedString.Key.kern, value: 2, range: NSMakeRange(0, attrString.length))
    
    
    // Swift 4.1--
    // 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 = "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
    
    0 讨论(0)
提交回复
热议问题