我正在尝试创建一个消息传递应用程序,并且遇到了一个非常奇怪的问题。

ios - 带有段落样式行间距的UILabel-LMLPHP

之所以在“Thomas”和文本气泡底部之间留出很大空间是因为UILabel正在创建另一行。目前,我正在使用attributedText属性设置标签的文本,并以NSMutableParagraphStyleline spacing传递8。如果我将line spacing设置为0,则“Thomas”和文本气泡底部之间的空间将消失,如下所示:

ios - 带有段落样式行间距的UILabel-LMLPHP

这是奇怪的地方。如果将段落line spacing设置回8,并向该行添加了几个字符,则会出现文本气泡,而没有多余的行:

ios - 带有段落样式行间距的UILabel-LMLPHP

非常感谢所有帮助:)

这是我的代码:

class MessageTableViewCell: UITableViewCell {
    var didSetupConstraints = false

    var thumbnail = UIImageView.newAutoLayoutView()
    let messageTailIcon = UIImageView.newAutoLayoutView()
    var messageView = UIView.newAutoLayoutView()
    var messageLabel = UILabel.newAutoLayoutView()

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupViews()
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setupViews() {
        thumbnail.image = UIImage(named: "ThomasBaldwin")
        thumbnail.layer.cornerRadius = 17.5
        thumbnail.clipsToBounds = true

        messageTailIcon.image = UIImage(named: "MessageTailIcon")

        messageView.backgroundColor = Application.greyColor
        messageView.layer.cornerRadius = 10

        let paragraphStyle = NSMutableParagraphStyle.new()
        paragraphStyle.lineSpacing = 8

        messageLabel.numberOfLines = 0
        messageLabel.layer.cornerRadius = 10
        messageLabel.attributedText = NSMutableAttributedString(
            string: "Thomas says hello",
            attributes: [
                NSFontAttributeName: UIFont(name: "AvenirNextLTPro-Regular", size: 12.5)!,
                NSForegroundColorAttributeName: UIColor.colorFromCode(0x262626),
                NSBackgroundColorAttributeName: Application.greyColor,
                NSKernAttributeName: 0.5,
                NSParagraphStyleAttributeName: paragraphStyle
            ]
        )

        contentView.addSubview(thumbnail)
        contentView.addSubview(messageView)
        messageView.addSubview(messageTailIcon)
        messageView.addSubview(messageLabel)
        updateConstraints()
    }

    override func updateConstraints() {
        if !didSetupConstraints {

            thumbnail.autoPinEdgeToSuperviewEdge(.Top, withInset: 15)
            thumbnail.autoPinEdgeToSuperviewEdge(.Leading, withInset: 8.5)
            thumbnail.autoSetDimensionsToSize(CGSize(width: 35, height: 35))

            messageView.autoPinEdgeToSuperviewEdge(.Top, withInset: 17.5)
            messageView.autoPinEdge(.Leading, toEdge: .Trailing, ofView: thumbnail, withOffset: 10)
            messageView.autoPinEdgeToSuperviewEdge(.Trailing, withInset: 24.5)
            messageView.autoPinEdgeToSuperviewEdge(.Bottom)

            messageTailIcon.autoPinEdgeToSuperviewEdge(.Top, withInset: 15)
            messageTailIcon.autoPinEdgeToSuperviewEdge(.Leading, withInset: -10)
            messageTailIcon.autoSetDimensionsToSize(CGSize(width: 18, height: 9))

            messageLabel.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsets(top: 8.5, left: 10, bottom: 8.5, right: 5), excludingEdge: .Trailing)
            messageLabel.autoPinEdgeToSuperviewEdge(.Trailing, withInset: 0, relation: .GreaterThanOrEqual)

            didSetupConstraints = true
        }

        super.updateConstraints()
    }

}

如果您想查看一个演示该问题的示例项目,我已将其推送到github

最佳答案

好的,所以最终锁定并给出简单答案,这仅与您的KERNING属性有关。看这个:

也不要理会红色单元格的大小,在应用程序中不会发生这种情况,这只是我的屏幕截图大小不同的产物,但是请自己尝试一下。注释掉字距调整并重新应用它,您将看到相同的内容

,与“Thomas”进行字距调整

ios - 带有段落样式行间距的UILabel-LMLPHP

,而不用“Thomas”字距调整

ios - 带有段落样式行间距的UILabel-LMLPHP

,与“托马斯说你好”的字距调整

ios - 带有段落样式行间距的UILabel-LMLPHP

,不与“Thomas说你好”字距紧调

ios - 带有段落样式行间距的UILabel-LMLPHP

我已经做了一切可能的检查代码,使用不同的约束的方法,甚至还使用了NSAttributedString的所有选项,唯一改变这种不良行为的是字距调整属性,它对所有类型的字体都执行了此操作,而不仅仅是Avenir。实际上,在此示例中使用的字体是根本不设置字体的系统字体,但是我现在尝试使用3种字体,效果相同,字距调整似乎已损坏或按预期工作对于Swift和/或ObjC,但我认为这实际上是一个错误。

大多数NSAttributedString选项,如果您想弄乱的东西:

    var myString1 = NSMutableAttributedString(string:"Thomas asdfadsf asdfasdfasdf asdfasdf asdfasdf \n asdfasdf asdf \n")

    let myString1Font1 = UIFont.systemFontOfSize(12.0)

    let originalNSString = myString1.string as NSString
    let myString1Range1 = originalNSString.rangeOfString(myString1.string)

    var myString1ParaStyle1 = NSMutableParagraphStyle()
    myString1ParaStyle1.alignment = NSTextAlignment.Natural
    myString1ParaStyle1.baseWritingDirection = NSWritingDirection.Natural
    myString1ParaStyle1.defaultTabInterval = 0.0
    myString1ParaStyle1.firstLineHeadIndent = 0.0
    myString1ParaStyle1.headIndent = 0.0
    myString1ParaStyle1.hyphenationFactor = 0.0
    myString1ParaStyle1.lineBreakMode = NSLineBreakMode.ByWordWrapping
    myString1ParaStyle1.lineHeightMultiple = 0.0
    myString1ParaStyle1.lineSpacing = 8.0
    myString1ParaStyle1.maximumLineHeight = 0.0
    myString1ParaStyle1.minimumLineHeight = 0.0
    myString1ParaStyle1.paragraphSpacing = 0.0
    myString1ParaStyle1.paragraphSpacingBefore = 0.0
    myString1ParaStyle1.tailIndent = 0.0

    myString1.addAttribute(NSKernAttributeName, value:0.5, range:myString1Range1)
    myString1.addAttribute(NSFontAttributeName, value:myString1Font1, range:myString1Range1)
    myString1.addAttribute(NSParagraphStyleAttributeName, value:myString1ParaStyle1, range:myString1Range1)
    myString1.addAttribute(NSBackgroundColorAttributeName, value:UIColor.redColor(), range:myString1Range1)
    myString1.addAttribute(NSForegroundColorAttributeName, value:UIColor.blackColor(), range:myString1Range1)

再说一次,这不是一个约束问题,我错了,这只是一个核心问题,这很糟糕,但这就是生活,也许这需要向雷达报告。

另外,您可以自己尝试一下,但是如果使用0或0.00000或任意多个零值,则使用Kerning都会产生错误的结果,我尝试过此操作,并且使您的标签字段弄乱了,就像字距调整会弄乱字段一样具有较大的值:
 NSKernAttributeName: 0.00000000000001

按住,我从外观上解决了它,设置该值,只需将其添加到示例项目中设置的段落样式变量中,即可使用字距调整功能,不确定是否适用于所有字体,但是它至少可以修复示例项目:
paragraphStyle.lineHeightMultiple = 1.5

这种方法的唯一问题是,它适用于一个单词或一行的行,您必须进行字数调整才能根据出现新行的时间来设置此“lineHeightMultiple”,这很糟糕,但它可以工作,显然,这不是一个很好的方法,但是如果您有1个衬线,则可以使用,如果有更多衬线,则需要进行调整,否则请关闭字距调整,并且在没有此线高倍数的情况下都可以解决。

好像行高在内部改变并将字符推到新行,但是apple并不能自动考虑字符宽度的这种变化。

事实上,我认为您正在寻找的答案根本不是字距,而是跟踪,这会使字母彼此分开。字距调整的问题是,字距调整会紧紧字体的字形并覆盖其某些行为,因此,这可能是一种可反感的效果,就像我们在此处看到的那样。

从苹果公司:



https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/TypoFeatures/TextSystemFeatures.html

如果确实需要字距调整,那么如果字体有任何可用的字体,则可能应该调整连字的字距调整值。

需要考虑的其他事情,这确实可行,但是它也大胆,因此已经不是您上面的样式所能匹配的东西,但是您可以通过以下方式玩弄:
let sytemDynamicFontDescriptor = UIFontDescriptor.preferredFontDescriptorWithTextStyle(UIFontTextStyleHeadline)
let size = sytemDynamicFontDescriptor.pointSize
let myString1Font1 = UIFont(descriptor: sytemDynamicFontDescriptor, size:size)

println(sytemDynamicFontDescriptor.fontAttributes())

messageLabel.numberOfLines = 0
messageLabel.layer.cornerRadius = 10

messageLabel.attributedText = NSMutableAttributedString(
    string: "Thomas asdfad as ",
    // string: "Thomas says hello", // switch back to this to see it display the text properly on one
    attributes: [
        NSFontAttributeName: myString1Font1,
        NSForegroundColorAttributeName: UIColor.blackColor(),
        NSBackgroundColorAttributeName: UIColor.redColor(),
        NSKernAttributeName: 0.5,
        NSParagraphStyleAttributeName: paragraphStyle
    ]
)

09-19 15:26