根据文本动态获取UILabel的高度为iOS 7.0和iOS 6.1返回不同的值

Posted

技术标签:

【中文标题】根据文本动态获取UILabel的高度为iOS 7.0和iOS 6.1返回不同的值【英文标题】:Dynamically getting height of UILabel according to Text return different Value for iOS 7.0 and iOS 6.1 【发布时间】:2013-11-19 10:19:56 【问题描述】:

我正在使用这个方法来动态获取 UILabel 的高度:

+(CGSize) GetSizeOfLabelForGivenText:(UILabel*)label Font:(UIFont*)fontForLabel Size:  (CGSize)LabelSize
    label.numberOfLines = 0;
    CGSize labelSize = [label.text sizeWithFont:fontForLabel constrainedToSize:LabelSize lineBreakMode:NSLineBreakByCharWrapping];
    return (labelSize);

如果我的代码在 ios 8 以下运行,通过此解决方案,我将获得 UILabel 的确切大小 但是如果我在 iOS7 上运行我的应用程序,那么它会返回一个不同的值。

【问题讨论】:

【参考方案1】:

您必须动态设置框架,如下所示:

在 iOS 6 到 iOS 12.2 上测试

斯威夫特:

let constrainedSize = CGSize(width: self.titleLable.frame.size.width, height:9999)

let attributesDictionary = [NSAttributedString.Key.font: UIFont.init(name: "HelveticaNeue", size: 11.0)]

let string = NSAttributedString.init(string: "textToShow", attributes: attributesDictionary as [NSAttributedString.Key : Any])

var requiredHeight = string.boundingRect(with: constrainedSize, options: .usesLineFragmentOrigin, context: nil)


if (requiredHeight.size.width > self.titleLable.frame.size.width) 
    requiredHeight = CGRect(x: 0, y: 0, width: self.titleLable.frame.size.width, height: requiredHeight.size.height)

var newFrame = self.titleLable.frame
newFrame.size.height = requiredHeight.size.height
self.titleLable.frame = newFrame

目标 C:

CGSize constrainedSize = CGSizeMake(self.resizableLable.frame.size.width  , 9999);

NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                      [UIFont fontWithName:@"HelveticaNeue" size:11.0], NSFontAttributeName,
                                      nil];

NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"textToShow" attributes:attributesDictionary];

CGRect requiredHeight = [string boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin context:nil];

if (requiredHeight.size.width > self.resizableLable.frame.size.width) 
    requiredHeight = CGRectMake(0,0, self.resizableLable.frame.size.width, requiredHeight.size.height);

CGRect newFrame = self.resizableLable.frame;
newFrame.size.height = requiredHeight.size.height;
self.resizableLable.frame = newFrame;

【讨论】:

您到底在哪里使用 maximumLabelSize ?这不起作用。 很好的解决方案。也很容易实现。 完美答案。为我工作。非常感谢你hh 请快速版本 @AwaisFayyaz:你本可以更新,但谢谢我现在更新了。【参考方案2】:

这是宽度和高度的整体解决方案。将这些放在您的 AppDelegate 中:

+(void)fixHeightOfThisLabel:(UILabel *)aLabel

    aLabel.frame = CGRectMake(aLabel.frame.origin.x,
                              aLabel.frame.origin.y,
                              aLabel.frame.size.width,
                              [AppDelegate heightOfTextForString:aLabel.text
                                                         andFont:aLabel.font
                                                         maxSize:CGSizeMake(aLabel.frame.size.width, MAXFLOAT)]);


+(CGFloat)heightOfTextForString:(NSString *)aString andFont:(UIFont *)aFont maxSize:(CGSize)aSize

    // iOS7
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
    
        CGSize sizeOfText = [aString boundingRectWithSize: aSize
                                                  options: (NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                               attributes: [NSDictionary dictionaryWithObject:aFont
                                                                                       forKey:NSFontAttributeName]
                                                  context: nil].size;

        return ceilf(sizeOfText.height);
    

    // iOS6
    CGSize textSize = [aString sizeWithFont:aFont
                          constrainedToSize:aSize
                              lineBreakMode:NSLineBreakByWordWrapping];
    return ceilf(textSize.height;


+(void)fixWidthOfThisLabel:(UILabel *)aLabel

    aLabel.frame = CGRectMake(aLabel.frame.origin.x,
                              aLabel.frame.origin.y,
                                [AppDelegate widthOfTextForString:aLabel.text
                                                          andFont:aLabel.font
                                                          maxSize:CGSizeMake(MAXFLOAT, aLabel.frame.size.height)],
                              aLabel.frame.size.height);


+(CGFloat)widthOfTextForString:(NSString *)aString andFont:(UIFont *)aFont maxSize:(CGSize)aSize

    // iOS7
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
    
        CGSize sizeOfText = [aString boundingRectWithSize: aSize
                                                  options: (NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                               attributes: [NSDictionary dictionaryWithObject:aFont
                                                                                       forKey:NSFontAttributeName]
                                                  context: nil].size;

        return ceilf(sizeOfText.width);
    

    // iOS6
    CGSize textSize = [aString sizeWithFont:aFont
                          constrainedToSize:aSize
                              lineBreakMode:NSLineBreakByWordWrapping];
    return ceilf(textSize.width);

然后要使用它,设置标签的文本:

label.numberOfLines = 0;
label.text = @"Everyone loves Stack OverFlow";

然后调用:

[AppDelegate fixHeightOfThisLabel:label];

注意:标签的 numberOfLines 必须设置为 0。 希望对您有所帮助。

【讨论】:

【参考方案3】:

如果您使用任何系统字体,它们在 iOS 7 中发生了变化,因此它们的大小会有所不同。


另外,sizeWithFont:constrainedToSize:lineBreakMode: 在 iOS 7 中已弃用。请改用 sizeWithAttributes:(如果您使用的是 iOS 7)

【讨论】:

【参考方案4】:

接受的答案并没有让我满意,所以我不得不在我的代码中挖掘这个:

CGSize possibleSize = [string sizeWithFont:[UIFont fontWithName:@"HelveticaNeue" size:10] //font you are using
                          constrainedToSize:CGSizeMake(skillsMessage.frame.size.width,9999)
                              lineBreakMode:NSLineBreakByWordWrapping];


CGRect newFrame = label.frame;
newFrame.size.height = possibleSize.height;
label.frame = newFrame;

【讨论】:

sizeWithFont 在 iOS7 中已弃用。 使用 CGSize boundingBox = [label.text boundingRectWithSize:.....【参考方案5】:

接受的答案太长。您可以使用以下内容:

+(CGSize) GetSizeOfLabelForGivenText:(UILabel*)label Font:(UIFont*)fontForLabel Size:  (CGSize) constraintSize
    label.numberOfLines = 0;
    CGRect labelRect = [label.text boundingRectWithSize:constraintSize options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:@NSFontAttributeName:fontForLabel context:nil];
    return (labelRect.size);

【讨论】:

【参考方案6】:

无论我通过这段代码得到什么高度(我在上面这个问题中写过的方法)。它提供浮点值 (86.4) 的高度,一旦我们得到它并尝试设置那个高度到 UILabel,但我们需要使用 ceil (87) 从高度获取值,而不是 (86.4) 的值。我已经用这种方法解决了我的问题。感谢您的回答。

【讨论】:

【参考方案7】:

这是我最后想出来的,希望这对你有帮助。我在iOS 7 UI Transition Guide 中检查了Apple 本身所做的iOS 版本,这涉及检查Foundation Framework 版本并使用#pragma 来禁止使用“- (CGSize)sizeWithFont:(UIFont *)font 来抑制已弃用:iOS 7 或更高版本引发的警告” constrainedToSize:(CGSize)size"。

+ (CGSize)getStringBoundingSize:(NSString*)string forWidth:(CGFloat)width withFont:(UIFont*)font

    CGSize maxSize = CGSizeMake(width, CGFLOAT_MAX);
    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) 
        // for iOS 6.1 or earlier
        // temporarily suppress the warning and then turn it back on
        // since sizeWithFont:constrainedToSize: deprecated on iOS 7 or later
        #pragma clang diagnostic push
        #pragma clang diagnostic ignored "-Wdeprecated-declarations"
            maxSize = [string sizeWithFont:font constrainedToSize:maxSize];
        #pragma clang diagnostic pop

     else 
        // for iOS 7 or later
        maxSize = [string sizeWithAttributes:@NSFontAttributeName:font];

    
    return maxSize;

【讨论】:

【参考方案8】:

我一直用sizeThatFits:

CGRect frame = myLabel.frame;
CGSize constraint = CGSizeMake(CGRectGetWidth(myLabel.frame), 20000.0f);
CGSize size = [myLabel sizeThatFits:constraint];
frame.size.height = size.height;
myLabel.frame = frame;

你可以试试这个

【讨论】:

【参考方案9】:

超级简单。只需获取文本的区域,除以宽度,然后四舍五入到适合您字体的最接近的高度。

+ (CGFloat)heightForText:(NSString*)text font:(UIFont*)font withinWidth:(CGFloat)width 
    CGSize size = [text sizeWithAttributes:@NSFontAttributeName:font];
    CGFloat area = size.height * size.width;
    CGFloat height = roundf(area / width);
    return ceilf(height / font.lineHeight) * font.lineHeight;

非常适合即插即用的解决方案。我经常在帮助类中使用它,尤其是对于动态大小的 UITableViewCells。

希望这对未来的其他人有所帮助!

【讨论】:

【参考方案10】:

sizeWithFont:constrainedToSize:lineBreakMode: 方法在 iOS7 中已弃用。 你应该改用sizeWithAttributes:

例子:

NSDictionary *fontAttributes = @NSFontAttributeName : [UIFont systemFontOfSize:15];
CGSize textSize = [self.myLabel.text sizeWithAttributes:fontAttributes];
CGFloat textWidth = textSize.width;
CGFloat textHeight = textSize.height;

【讨论】:

【参考方案11】:

我有一种情况,我需要根据文本动态设置标签的高度。我正在使用 Xcode 7.1,我的项目部署目标是 7.0,但我在 iOS 9 模拟器上对其进行了测试,以下解决方案对我有用。这是解决方案: 首先,你们将创建一个这样的字典:

NSDictionary *attributes = @NSFontAttributeName:self.YOUR_LABEL.font;

现在我们将计算文本的高度和宽度并传递新创建的字典。

    CGRect rect = [YOUR_TEXT_STRING boundingRectWithSize:CGSizeMake(LABEL_WIDTH, CGFLOAT_MAX)
                                          options:NSStringDrawingUsesLineFragmentOrigin
                                       attributes:attributes
                                          context:nil];

然后我们将设置我们的标签的框架:

    self.YOUR_LABEL.frame = CGRectMake(self.YOUR_LABEL.frame.origin.x, self.YOUR_LABEL.frame.origin.y, self.YOUR_LABEL.frame.size.width, rect.size.height);

这就是我根据文本成功设置标签框架的方法。

【讨论】:

【参考方案12】:

这个方法是我从iOS 7到iOS 11.4使用和测试的

+ (CGFloat)getLabelHeight:(UILabel*)label

    NSParameterAssert(label);
    CGSize limitLabel = CGSizeMake(label.frame.size.width, CGFLOAT_MAX);
    CGSize size;

    NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
    CGSize labelBox = [label.text boundingRectWithSize: limitLabel
                                                  options: NSStringDrawingUsesLineFragmentOrigin
                                               attributes: @ NSFontAttributeName:label.font 
                                                  context: context].size;

    size = CGSizeMake(ceil(labelBox.width), ceil(labelBox.height));
    return size.height;

所以你可以这样使用:

CGFloat sizeOfFontTest = 12.0;
    UILabel *testLabel = [[UILabel alloc] initWithFrame: CGRectMake(0, 0, 100, 0)];
    [testLabel setFont: [UIFont systemFontOfSize: sizeOfFontTest]];
    [testLabel setText: @"Hello *** Large String Example"];

    CGFloat heightTestLabel = [self getLabelHeight: testLabel];

    [testLabel setFrame: CGRectMake(testLabel.frame.origin.x, testLabel.frame.origin.y, testLabel.frame.size.width, heightAddrsLab)];
    [testLabel setNumberOfLines: sizeOfFontTest / heightTestLabel];

【讨论】:

【参考方案13】:

此代码用于通过使用按钮功能来顺时针移动四个标签与按钮点击:

(void)onclick

    CGRect newFrame;
    CGRect newFrame1 = lbl1.frame;
    CGRect newFrame2 = lbl2.frame;
    CGRect newFrame3 = lbl3.frame;
    CGRect newFrame4 = lbl4.frame;
    lbl1.frame=newFrame;
    lbl4.frame=newFrame1;
    lbl3.frame=newFrame4;
    lbl2.frame=newFrame3;
    lbl1.frame=newFrame2;

【讨论】:

以上是关于根据文本动态获取UILabel的高度为iOS 7.0和iOS 6.1返回不同的值的主要内容,如果未能解决你的问题,请参考以下文章

如何将 UIImage 设置为 UITableView Cell,它根据我在 UILabel 中输入的文本动态计算单元格高度?

如何将UIImage设置为UITableView Cell,根据我在UILabel中输入的文本动态计算单元格高度?

根据内容动态改变UILabel的高度

iOS UILabel讲解以及根据字符串长度自动适应宽度和高度

iOS-UILabel根据文本字体大小计算label宽度;以及自适应高度

在tableview ios中使用UILabel的单元格的动态高度