我有一个UILabel,其文本是通过-setAttributedText:
动态设置的
NSAttributedString包含各种动态属性,即不同字符或样式,用于不同的字符范围。 UILabel的宽度受到约束(通过自动布局),高度可变(numberOfLines = 0)。
我需要确定的是在给定NSAttributedString和宽度约束的情况下呈现的文本行数。
请注意,我不是在寻找标签的高度,我正在寻找渲染线的数量。另请注意,我无法根据font.lineHeight执行任何计算,因为整个NSAttributedString中的字体不同。
对于某些背景,要为具有1行的标签设置label.textAlignment=NSTextAlignmentCenter
,为具有2行或更多行的标签设置label.textAlignment=NSTextAlignmentLeft
。我会在自动布局之后在-[UIViewController viewDidLayoutSubviews]
中执行此操作并且UILabel已完成其业务。或者也许有一种更简单的方法来实现相同的目标。
答案 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;
希望这会有所帮助......