如何在UILabel中控制行距


273

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



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

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

请参考以下链接解决方案,斯威夫特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.