Answers:
您可以计算字符串的宽度,然后查看宽度是否大于label.bounds.size.width
NSString UIKit Additions具有几种用于计算具有特定字体的字符串大小的方法。但是,如果标签具有minimumFontSize,则允许系统将文本缩小到该大小。在这种情况下,您可能要使用sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:。
CGSize size = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}];
if (size.width > label.bounds.size.width) {
...
}
numberOfLines
返回用于显示文本的最大行数,如UILabel
类参考中所述:developer.apple.com/library/ios/documentation/UIKit/Reference/…–
Swift(作为扩展名)-适用于多行uilabel:
swift4 :(attributes
参数boundingRect
稍有变化)
extension UILabel {
var isTruncated: Bool {
guard let labelText = text else {
return false
}
let labelTextSize = (labelText as NSString).boundingRect(
with: CGSize(width: frame.size.width, height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
attributes: [.font: font],
context: nil).size
return labelTextSize.height > bounds.size.height
}
}
swift3:
extension UILabel {
var isTruncated: Bool {
guard let labelText = text else {
return false
}
let labelTextSize = (labelText as NSString).boundingRect(
with: CGSize(width: frame.size.width, height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
attributes: [NSFontAttributeName: font],
context: nil).size
return labelTextSize.height > bounds.size.height
}
}
swift2:
extension UILabel {
func isTruncated() -> Bool {
if let string = self.text {
let size: CGSize = (string as NSString).boundingRectWithSize(
CGSize(width: self.frame.size.width, height: CGFloat(FLT_MAX)),
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: [NSFontAttributeName: self.font],
context: nil).size
if (size.height > self.bounds.size.height) {
return true
}
}
return false
}
}
编辑:我只是看到我的答案被否决,但我给出的代码段已被弃用。
现在最好的方法是(ARC):
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.lineBreakMode = mylabel.lineBreakMode;
NSDictionary *attributes = @{NSFontAttributeName : mylabel.font,
NSParagraphStyleAttributeName : paragraph};
CGSize constrainedSize = CGSizeMake(mylabel.bounds.size.width, NSIntegerMax);
CGRect rect = [mylabel.text boundingRectWithSize:constrainedSize
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:attributes context:nil];
if (rect.size.height > mylabel.bounds.size.height) {
NSLog(@"TOO MUCH");
}
请注意,计算出的大小不是整数值。因此,如果您执行类似的操作int height = rect.size.height
,您将失去一些浮点精度,并且可能会得到错误的结果。
旧答案(不建议使用):
如果标签是多行的,则可以使用以下代码:
CGSize perfectSize = [mylabel.text sizeWithFont:mylabel.font constrainedToSize:CGSizeMake(mylabel.bounds.size.width, NSIntegerMax) lineBreakMode:mylabel.lineBreakMode];
if (perfectSize.height > mylabel.bounds.size.height) {
NSLog(@"TOO MUCH");
}
您可以使用UILabel进行分类
- (BOOL)isTextTruncated
{
CGRect testBounds = self.bounds;
testBounds.size.height = NSIntegerMax;
CGRect limitActual = [self textRectForBounds:[self bounds] limitedToNumberOfLines:self.numberOfLines];
CGRect limitTest = [self textRectForBounds:testBounds limitedToNumberOfLines:self.numberOfLines + 1];
return limitTest.size.height>limitActual.size.height;
}
textRectForBounds:limitedToNumberOfLines:
“您不应该直接调用此方法” ...
setNeedsLayout()
layoutIfNeeded()
在方法的开头添加了:
使用此类别来查找标签在iOS 7及更高版本上是否被截断。
// UILabel+Truncation.h
@interface UILabel (Truncation)
@property (nonatomic, readonly) BOOL isTruncated;
@end
// UILabel+Truncation.m
@implementation UILabel (Truncation)
- (BOOL)isTruncated
{
CGSize sizeOfText =
[self.text boundingRectWithSize:CGSizeMake(self.bounds.size.width, CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:@{ NSFontAttributeName : label.font }
context: nil].size;
if (self.frame.size.height < ceilf(sizeOfText.height))
{
return YES;
}
return NO;
}
@end
迅捷3
您可以在分配字符串后计算行数,并与标签的最大行数进行比较。
import Foundation
import UIKit
extension UILabel {
func countLabelLines() -> Int {
// Call self.layoutIfNeeded() if your view is uses auto layout
let myText = self.text! as NSString
let attributes = [NSFontAttributeName : self.font]
let labelSize = myText.boundingRect(with: CGSize(width: self.bounds.width, height: CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: attributes, context: nil)
return Int(ceil(CGFloat(labelSize.height) / self.font.lineHeight))
}
func isTruncated() -> Bool {
if (self.countLabelLines() > self.numberOfLines) {
return true
}
return false
}
}
要添加到iDev的答案中,应使用intrinsicContentSize
代替frame
,以使其适用于自动版式
- (BOOL)isTruncated:(UILabel *)label{
CGSize sizeOfText = [label.text boundingRectWithSize: CGSizeMake(label.intrinsicContentSize.width, CGFLOAT_MAX)
options: (NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes: [NSDictionary dictionaryWithObject:label.font forKey:NSFontAttributeName] context: nil].size;
if (self.intrinsicContentSize.height < ceilf(sizeOfText.height)) {
return YES;
}
return NO;
}
就是这个。这与配合使用attributedText
,然后又恢复text
原状,这对于处理多个字体系列,大小甚至NSTextAttachments的我们人们来说非常有意义!
使用autolayout可以很好地工作,但是很显然,在我们检查之前必须先定义和设置约束isTruncated
,否则标签本身甚至不知道如何进行布局,因此甚至无法知道其是否被截断。
它不工作,只是一个普通的来处理这个问题NSString
和sizeThatFits
。我不确定人们是如何获得积极成果的。正如许多次提到的那样,BTW sizeThatFits
根本不是理想的选择,因为它考虑到numberOfLines
了最终的大小,这违背了我们试图做的全部目的,因为无论其被截断与否,它isTruncated
总是会返回false
。
extension UILabel {
var isTruncated: Bool {
layoutIfNeeded()
let rectBounds = CGSize(width: bounds.width, height: .greatestFiniteMagnitude)
var fullTextHeight: CGFloat?
if attributedText != nil {
fullTextHeight = attributedText?.boundingRect(with: rectBounds, options: .usesLineFragmentOrigin, context: nil).size.height
} else {
fullTextHeight = text?.boundingRect(with: rectBounds, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil).size.height
}
return (fullTextHeight ?? 0) > bounds.size.height
}
}
这是Swift 3中的选定答案(作为扩展)。OP正在询问大约1个线路标签。我在这里尝试的许多快速答案都特定于多行标签,并且在单行标签上未正确标记。
extension UILabel {
var isTruncated: Bool {
guard let labelText = text as? NSString else {
return false
}
let size = labelText.size(attributes: [NSFontAttributeName: font])
return size.width > self.bounds.width
}
}
这适用于iOS 8:
CGSize size = [label.text boundingRectWithSize:CGSizeMake(label.bounds.size.width, NSIntegerMax) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : label.font} context:nil].size;
if (size.height > label.frame.size.height) {
NSLog(@"truncated");
}
我写了一个用于处理UILabel的截断的类别。适用于iOS 7及更高版本。希望能帮助到你 ! uilabel尾部截断
@implementation UILabel (Truncation)
- (NSRange)truncatedRange
{
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:[self attributedText]];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:[self bounds].size];
textContainer.lineFragmentPadding = 0;
[layoutManager addTextContainer:textContainer];
NSRange truncatedrange = [layoutManager truncatedGlyphRangeInLineFragmentForGlyphAtIndex:0];
return truncatedrange;
}
- (BOOL)isTruncated
{
return [self truncatedRange].location != NSNotFound;
}
- (NSString *)truncatedText
{
NSRange truncatedrange = [self truncatedRange];
if (truncatedrange.location != NSNotFound)
{
return [self.text substringWithRange:truncatedrange];
}
return nil;
}
@end
extension UILabel {
public func resizeIfNeeded() -> CGFloat? {
guard let text = text, !text.isEmpty else { return nil }
if isTruncated() {
numberOfLines = 0
sizeToFit()
return frame.height
}
return nil
}
func isTruncated() -> Bool {
guard let text = text, !text.isEmpty else { return false }
let size: CGSize = text.size(withAttributes: [NSAttributedStringKey.font: font])
return size.width > self.bounds.size.width
}
}
您可以计算字符串的宽度,然后查看宽度是否大于标签宽度。
为了增加@iDev所做的事情,我修改了self.frame.size.height
使用label.frame.size.height
,也没有使用NSStringDrawingUsesLineFontLeading
。经过这些修改后,我获得了截断发生时间的完美计算(至少对于我而言)。
- (BOOL)isTruncated:(UILabel *)label {
CGSize sizeOfText = [label.text boundingRectWithSize: CGSizeMake(label.bounds.size.width, CGFLOAT_MAX)
options: (NSStringDrawingUsesLineFragmentOrigin)
attributes: [NSDictionary dictionaryWithObject:label.font forKey:NSFontAttributeName] context: nil].size;
if (label.frame.size.height < ceilf(sizeOfText.height)) {
return YES;
}
return NO;
}
我有问题,boundingRect(with:options:attributes:context:)
使用自动布局时(设置一个最大高度)和属性文本与NSParagraph.lineSpacing
行之间的间距被忽略(即使传递attributes
到boundingRect
方法中也是如此),因此标签被认为不被截断。
我发现的解决方案是使用UIView.sizeThatFits
:
extension UILabel {
var isTruncated: Bool {
layoutIfNeeded()
let heightThatFits = sizeThatFits(bounds.size).height
return heightThatFits > bounds.size.height
}
}
因为以上所有答案均使用折旧方法,所以我认为这可能很有用:
- (BOOL)isLabelTruncated:(UILabel *)label
{
BOOL isTruncated = NO;
CGRect labelSize = [label.text boundingRectWithSize:CGSizeFromString(label.text) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : label.font} context:nil];
if (labelSize.size.width / labelSize.size.height > label.numberOfLines) {
isTruncated = YES;
}
return isTruncated;
}
要处理iOS 6(是的,我们中有些人仍然必须这样做),这是@iDev答案的又一个扩展。关键要点是,对于iOS 6,在调用sizeThatFits之前确保UILabel的numberOfLines设置为0;如果不是,它会为您提供一个结果,提示“绘制标签文本需要用到绘制numberOfLines个高度的点”。
- (BOOL)isTruncated
{
CGSize sizeOfText;
// iOS 7 & 8
if([self.text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)])
{
sizeOfText = [self.text boundingRectWithSize:CGSizeMake(self.bounds.size.width,CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:@{NSFontAttributeName:self.font}
context:nil].size;
}
// iOS 6
else
{
// For iOS6, set numberOfLines to 0 (i.e. draw label text using as many lines as it takes)
// so that siteThatFits works correctly. If we leave it = 1 (for example), it'll come
// back telling us that we only need 1 line!
NSInteger origNumLines = self.numberOfLines;
self.numberOfLines = 0;
sizeOfText = [self sizeThatFits:CGSizeMake(self.bounds.size.width,CGFLOAT_MAX)];
self.numberOfLines = origNumLines;
}
return ((self.bounds.size.height < sizeOfText.height) ? YES : NO);
}
确保在viewDidLayoutSubviews中调用其中任何一个。
public extension UILabel {
var isTextTruncated: Bool {
layoutIfNeeded()
return text?.boundingRect(with: CGSize(width: bounds.width, height: .greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font!], context: nil).size.height ?? 0 > bounds.size.height
}
var isAttributedTextTruncated: Bool {
layoutIfNeeded()
return attributedText?.boundingRect(with: CGSize(width: bounds.width, height: .greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil).size.height ?? 0 > bounds.size.height
}
}
SWIFT 5
设置为仅显示3行的多行UILabel的示例。
let labelSize: CGSize = myLabel.text!.size(withAttributes: [.font: UIFont.systemFont(ofSize: 14, weight: .regular)])
if labelSize.width > myLabel.intrinsicContentSize.width * 3 {
// your label will truncate
}
尽管用户可以选择返回键,而无需增加“文本宽度”,而是添加额外的一行,但在这种情况下,也可能会有用。
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
// return pressed
}
}
Swift 3解决方案
我认为最好的办法是(1)创建一个UILabel
具有相同属性的标签,你的截断检查,(2)调用.sizeToFit()
,(3)与实际的标签比较假标签的属性。
例如,如果要检查宽度变化的单行标签是否被截断,则可以使用以下扩展名:
extension UILabel {
func isTruncated() -> Bool {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: CGFloat.greatestFiniteMagnitude, height: self.bounds.height))
label.numberOfLines = 1
label.font = self.font
label.text = self.text
label.sizeToFit()
if label.frame.width > self.frame.width {
return true
} else {
return false
}
}
}
...但是同样,您可以轻松修改以上代码以适合您的需求。因此,假设您的标签是多行的并且具有不同的高度。然后,扩展名将如下所示:
extension UILabel {
func isTruncated() -> Bool {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: self.bounds.width, height: CGFloat.greatestFiniteMagnitude))
label.numberOfLines = 0
label.font = self.font
label.text = self.text
label.sizeToFit()
if label.frame.height > self.frame.height {
return true
} else {
return false
}
}
}
设置标签的title属性是否容易,将其设置为悬停时将显示完整标签。
您可以计算标签的长度和div的宽度(转换为长度-jQuery / Javascript-如何将像素值(20px)转换为数字值(20))。
如果长度大于div宽度,则设置jquery以设置标题。
var divlen = parseInt(jQuery("#yourdivid").width,10);
var lablen =jQuery("#yourlabelid").text().length;
if(lablen < divlen){
jQuery("#yourlabelid").attr("title",jQuery("#yourlabelid").text());
}