如何在UILabel中控制行距


273

如果将多个行放在一个文本中,是否可以减少文本之间的间距UILabel?我们可以设置框架,字体大小和行数。我想缩小该标签中两行之间的间距。



2
我是否可以建议您接受对iOS 6.0及更高版本正确的答案之一?当前接受的答案已过期。
Mark Amery 2013年

对于每行使用一个新的UILabel,然后将所有标签嵌入到一个StackView。最后调整spacingStackView。请记住将它们垂直堆叠。
亲爱的

请参考以下链接解决方案,斯威夫特2 stackoverflow.com/a/39158698/6602495
斯纳

有关情节提要调整和其他详细信息,请参阅stackoverflow.com/a/44325650/342794
lal

Answers:


261

我考虑过要在此答案中添加一些新内容,因此我觉得还不错……这是一个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或创建多个标签。”

请参阅:设置UILabel行距


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


23
从iOS 6.0开始,您可以通过NSAttributedString(通过Xcode的界面生成器中的UILable的属性提供)对其进行控制。
ıɾuǝʞ

13
有趣的是,据我所知,您可以在行之间增加额外的间距,但不能通过NSParagraphStyle使用来减小间距NSAttributedString。(我可能需要对其他可修改属性进行更多测试,但该lineSpacing属性仅允许您增加它。)
Livingtech

请参阅我的答案以查看使用NSAttributedString的方法
d.ennis 2013年

2
@livingtech真是令人生气,我相信你是正确的。您找到任何解决方法了吗?
Dom Vinyard 2014年

7
只是为了阐明该线程中的内容。如果要缩小行距,请将行高设置为1.0,然后将LineHeightMultiple设置为小于1.0的较低值,例如:[paragraphStyle setLineHeightMultiple:0.8]或
paradiseStyle.lineHeightMultiple

401

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

在此处输入图片说明


1
利用故事板的更多优势!
艾伦

22
@PaperThick在6.1.1中有相同的问题。它“哈林摇”几分钟。不知道如何解决它:) Xcode Shaking
Anton Gaenko

8
有没有办法这样设置自定义字体?我似乎无法将helvetica neue更改为任何其他字体。
Marcos Curvello 2015年

2
如果启用“属性”,然后将文件作为源代码打开,则可以手动编辑“ lineHeightMultiple”,从而绕过Harlem Shake错误
ED-209

2
@azdev对于仍然在看这个的人来说,我正在等待Xcode 7.3的更新,但是我认为这是第一个没有问题的版本
LulzCow 2016年

103

从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;

1
attributedString必须是一个NSMutableAttributedString(不NSAttributedString)
麦克小号

14
第一行代码应为NSMutableAttributedString *attributedString = [NSMutableAttributedString alloc]initWithString:@"sample text"];
艾伦(Allen)

lineSpacing属性NSMutableParagraphStyle永远不会为负,因此无法使用这种方法来减小行高。要回答这个问题,您必须使用另一个属性,请参阅@ d.ennis答案。
Theo 2015年

81

这里说明的解决方案对我不起作用。我发现使用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
行高取决于字体大小。行距就是行距。您可以通过设置最小/最大行高来解决问题,但这仅仅是因为您当前使用的字体大小不大于行高边界。根据文档:“ ...超过此高度的字形和图形将与相邻的行重叠...尽管此限制适用于行本身,但行间距在相邻的行之间增加了额外的空间。”
阿里·布拉金斯基

+1,如果要减小行间距,这是您要执行的操作。默认情况下,实际行距很可能为0,这就是为什么人们报告您只能增加它的原因。间距太大的问题来自线高太大,这就是为什么它将在99%的时间完成工作的原因。
lawicko 2015年

1
这是唯一的答案,我可以发现,使用实际的行高值(而不是一个比率)共同设计的应用程序,如Photoshop,素描,CSS等
阿尔伯特Bori的

35

我做了一个简单的扩展,对我来说非常有效:

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)

请记住,如果您同时也在此故事板中使用故事板时进行了此操作,请确保将标签的行设置为0
Honey

您为什么不直接设置lineSpacing和忘记设置lineHeightMultiple
亲爱的

因为降低行高的关键是'lineHeightMultiple',所以没有lineSpacing
Agustin Meriles'August '16

说你想把行高设为1.4,为什么你不能写.lineSpacing = 1.4而忘了一切呢.lineHeightMultiple
Honey

哈哈!我尝试了,但没有工作,但是我想知道为什么我在这里没有使用您的机制看不到其他答案,我的意思是他们只是直接设置lineSpacing。请参阅已接受的答案...
亲爱的

33

从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

2
添加行“ paragraphStyle.alignment = self.textAlignment”以保持原始对齐方式。否则,文本将保持左对齐。
Nithin Michael

对于任何在大文本上遗漏了省略号的人,请使用:段落样式.lineBreakMode = .byTruncatingTail
christostsang



11

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

7

根据@Mike的Answer,减少的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;
    }

6

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

5

我找到了一种可以设置实际线条高度(不是因素)的方法,它甚至可以在Interface Builder中实时渲染。请按照以下说明进行操作。代码是用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。等待项目构建(构建必须成功!)。

为您的UILabel指定类


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

在属性中设置线高


2

这是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,对吗?
Pavel Alexeev

上面的代码按原样似乎对我有用。但是也许你是对的。您尝试过零钱吗?@PavelAlexeev
帕特曼

不,我坚持使用lineSpacing而不是lineHeightMultiple :)
Pavel Alexeev

1

在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设置为attributedText:

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

显然,我添加了一堆您可能不需要的参数。随便玩-随时重写方法-我一直在寻找一堆不同的答案,因此我想将整个扩展发布出来,以防它对某人有所帮助... -rab


1

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
}

1

另一个答案...如果要以编程方式传递字符串,则需要传递属性字符串而不是常规字符串并更改其样式。(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;

1

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

1

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

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

这应该有所帮助。然后,您可以在情节提要中将标签分配给此自定义类,并直接在属性中使用其参数。
罗素·沃威克

请不要在评论中添加与您的答案相关的内容。您的答案应该会有所帮助,而不必阅读所有注释
Neuron

1

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

0

这段代码对我有用(肯定是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;

0

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

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

-5

作为一种快速,简单,智能的解决方法:

对于行数不多的UILabel,可以改用stackViews。

  1. 为每一行写一个新标签。
  2. 将它们嵌入到StackView中。(选择两个标签->编辑器->嵌入--StackView
  3. 调整SpacingStackView到所需的数量

确保将它们垂直堆叠。此解决方案也适用于自定义字体。

在此处输入图片说明


FWIW这是一个糟糕但可行的解决方案。因此,我保留了它。
亲爱的

我也看到了iOS开发人员使用stackviews创建图形的原理。Stackviews非常强大
蜂蜜
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.