具有固定宽度和NSAttributedString的UILabel的渲染行数

时间:2014-12-29 04:50:18

标签: ios objective-c iphone

我有一个UILabel,其文本是通过-setAttributedText:动态设置的 NSAttributedString包含各种动态属性,即不同字符或样式,用于不同的字符范围。 UILabel的宽度受到约束(通过自动布局),高度可变(numberOfLines = 0)。

我需要确定的是在给定NSAttributedString和宽度约束的情况下呈现的文本行数。

请注意,我不是在寻找标签的高度,我正在寻找渲染线的数量。另请注意,我无法根据font.lineHeight执行任何计算,因为整个NSAttributedString中的字体不同。

对于某些背景,要为具有1行的标签设置label.textAlignment=NSTextAlignmentCenter,为具有2行或更多行的标签设置label.textAlignment=NSTextAlignmentLeft。我会在自动布局之后在-[UIViewController viewDidLayoutSubviews]中执行此操作并且UILabel已完成其业务。或者也许有一种更简单的方法来实现相同的目标。

3 个答案:

答案 0 :(得分:5)

这是Swift 3版本

extension NSAttributedString {

    func numberOfLines(with width: CGFloat) -> Int {

        let path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: width, height: CGFloat(MAXFLOAT)))
        let frameSetterRef : CTFramesetter = CTFramesetterCreateWithAttributedString(self as CFAttributedString)
        let frameRef: CTFrame = CTFramesetterCreateFrame(frameSetterRef, CFRangeMake(0, 0), path.cgPath, nil)

        let linesNS: NSArray  = CTFrameGetLines(frameRef)

        guard let lines = linesNS as? [CTLine] else { return 0 }
        return lines.count
    }
}

希望这有帮助

答案 1 :(得分:0)

从技术上讲,这并没有回答如何学习渲染文本行数的问题,但我确实找到了解决问题的方法,所以我想我还是会发布它。

我最终做的是删除标签上的宽度自动布局约束(实际上是超视图的前导和尾随约束)并在容器约束中水平添加一个中心。然后在-[UIViewController viewDidLayoutSubviews]中设置label.preferredMaxLayoutWidth=self.view.frame.size.width-margin。标签是textAlignment=NSTextAlignmentLeft

如果标签只有一条线,则实现了标签居中的相同效果,如果标签是两条或更多条,则标签左对齐。

答案 2 :(得分:-2)

您可以将UILabel设置为NSMutableAttributedString,如下所示:

UILabel *contentLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,0,200,100)];
[contentLabel setLineBreakMode:NSLineBreakByWordWrapping];
[contentLabel setNumberOfLines:0];
[contentLabel setFont:[UIFont systemFontOfSize:13];

NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"hello I am a long sentence that should break over multiple lines"];
[string addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:13] range:NSMakeRange(0, [string length])];

contentLabel.attributedText = string;

希望这会有所帮助......

相关问题