核心文本 - NSAttributedString线条高度做得对吗?

Sch*_*oob 55 nsattributedstring core-text line-spacing

我完全沉浸在Core Text的行距中.我正在使用NSAttributedString并在其上指定以下属性: - kCTFontAttributeName - kCTParagraphStyleAttributeName

从这里创建CTFrameSetter并将其绘制到上下文中.

在段落样式属性中,我想指定行的高度.

当我使用kCTParagraphStyleSpecifierLineHeightMultiple时,每一行都会在文本顶部接收填充,而不是在此高度的中间显示文本.

当我使用kCTParagraphStyleSpecifierLineSpacing时,填充将添加到文本的底部.

请帮助我达到指定的行高,文本(字形)位于该高度的中间,而不是位于行的底部或顶部的文本.

如果没有明确创建CTLine的路线等,这是不可能的?

Tie*_*eme 102

如果您正在为iOS> = 6.0开发,则可以使用此方法

NSInteger strLength = [myString length];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setLineSpacing:24];
[attString addAttribute:NSParagraphStyleAttributeName
                  value:style
                  range:NSMakeRange(0, strLength)];
Run Code Online (Sandbox Code Playgroud)

  • lineHeightMultiple也是使用而不是lineSpacing的另一个不错的选择 - 我通常将其设置为1.2. (14认同)
  • lineHeightMultiple可以通过将其设置为小于1来减小行高.`[style setLineHeightMultiple:0.8]` (7认同)
  • 什么是attString? (4认同)
  • @Deco - 它是一个`NSMutableAttributedString` (4认同)
  • 如何将行间距减少到默认空间以下.此方法仅用于增加高度. (3认同)
  • 是的。但请记住,`setLineHeightMultiple` 在 iOS 上不可用,它仅适用于 Mac OSX。 (2认同)
  • NSMutableParagraphStyle.lineHeightMultiple是iOS 6.0及更高版本。 (2认同)

Sch*_*oob 12

我对以下陈述仍然没有100%的信心,但似乎有道理.请纠正我错在哪里.

线高(前导)指的是连续线型的基线之间的距离.这里的基线可以解释为文本所在的虚线.

间距是线之间的空间.空格出现在文本行之后.

我最终使用以下解决方案解决了我的问题:

// NOT SURE WHAT THE THEORY BEHIND THIS FACTOR IS. WAS FOUND VIA TRIAL AND ERROR.
    CGFloat factor = 14.5/30.5;
    CGFloat floatValues[4];
    floatValues[0] = self.lineHeight * factor/(factor + 1);
    floatValues[1] = self.lineHeight/(factor + 1);
    floatValues[2] = self.lineHeight;
Run Code Online (Sandbox Code Playgroud)

此矩阵与NSAttributedString的段落样式参数一起使用:

CTParagraphStyleSetting paragraphStyle[3];

paragraphStyle[0].spec = kCTParagraphStyleSpecifierLineSpacing;
paragraphStyle[0].valueSize = sizeof(CGFloat);
paragraphStyle[0].value = &floatValues[0];

paragraphStyle[1].spec = kCTParagraphStyleSpecifierMinimumLineHeight;
paragraphStyle[1].valueSize = sizeof(CGFloat);
paragraphStyle[1].value = &floatValues[1];

paragraphStyle[2].spec = kCTParagraphStyleSpecifierMaximumLineHeight;
paragraphStyle[2].valueSize = sizeof(CGFloat);
paragraphStyle[2].value = &floatValues[2];

CTParagraphStyleRef style = CTParagraphStyleCreate((const CTParagraphStyleSetting*) &paragraphStyle, 3);
[attributedString addAttribute:(NSString*)kCTParagraphStyleAttributeName value:(id)style range:NSMakeRange(0, [string length])];
CFRelease(style);
Run Code Online (Sandbox Code Playgroud)

希望这有助于某人.当我发现更多相关信息时,我会更新这个答案.

  • 对不起,您能否稍微扩展您的代码段?什么类型的对象是`paragraphStyle`?那么`lineHeight`和`floatValues`呢?谢谢! (3认同)
  • 我用它来处理`floatValues`,用`CGFloat floatValues [4];`和`paragraphStyles`声明``CTParagraphStyleSetting paragraphStyle [3]; (3认同)

Enr*_*que 9

Swift 3中:

    let textFont = UIFont(name: "Helvetica Bold", size: 20)!
    let textColor = UIColor(white: 1, alpha: 1)      // White
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.paragraphSpacing = 20             // Paragraph Spacing
    paragraphStyle.lineSpacing = 40                  // Line Spacing

    let textFontAttributes = [
        NSFontAttributeName: textFont,
        NSForegroundColorAttributeName: textColor,
        NSParagraphStyleAttributeName: paragraphStyle
        ] as [String : Any]
Run Code Online (Sandbox Code Playgroud)


Kru*_*nal 7

您可以从故事板以及以编程方式设置/更新行间距和行高倍数.

来自Interface Builder:

在此输入图像描述

编程方式:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

现在调用扩展功能

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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

斯威夫特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
Run Code Online (Sandbox Code Playgroud)


Mat*_*mar 5

我尝试了所有这些答案,但要真正获得 Sketch 或 Zeplin 设计文件中通常出现的精确线高,您需要:

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
...
Run Code Online (Sandbox Code Playgroud)