77 Stimmen

Wie berechnet man die Höhe eines UILabels dynamisch?

Ich möchte die Anzahl der Zeilen und die Höhe des UILabels dynamisch aus dem gegebenen Text berechnen.

88voto

Versuche dies

// UILabel *myLabel;

CGSize labelSize = [myLabel.text sizeWithFont:myLabel.font 
                            constrainedToSize:myLabel.frame.size 
                                lineBreakMode:NSLineBreakByWordWrapping];

CGFloat labelHeight = labelSize.height;

int lines = [myLabel.text sizeWithFont:myLabel.font 
                     constrainedToSize:myLabel.frame.size 
                         lineBreakMode:NSLineBreakByWordWrapping].height/16; 
             // '16' ist Schriftgröße

oder

int lines = labelHeight/16;

NSLog(@"Anzahl der Zeilen: %i \n\n",lines);  

oder

int lines = [myLabel.text sizeWithFont:myLabel.font 
                     constrainedToSize:myLabel.frame.size 
                         lineBreakMode:UILineBreakModeWordWrap].height /myLabel.font.pointSize; //Schriftgröße aus der Schriftart abrufen

Durch die Verwendung von Kategorien, erstellen Sie die Kategorieklasse mit dem Namen

UILabel+UILabelDynamicHeight.h

UILabel+UILabelDynamicHeight.m

Keine Sorge mehr um die Höhenberechnung. Bitte überprüfen Sie die unten stehende Implementierung.

Aktualisierungen für iOS7 & höher, iOS 7 unten: Dynamische Berechnung der UILabel-Höhe

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
#define iOS7_0 @"7.0"

UILabel+UILabelDynamicHeight.h

#import 
@interface UILabel (UILabelDynamicHeight)

#pragma mark - Berechnen der Größe des mehrzeiligen Labels
/*====================================================================*/

    /* Berechnen der Größe des mehrzeiligen Labels */

/*====================================================================*/
/**
 *  Gibt die Größe des Labels zurück
 *
 *  @param aLabel Zur Berechnung der Höhe zu verwenden
 *
 *  @return Größe des Labels
 */
 -(CGSize)sizeOfMultiLineLabel;

@end

UILabel+UILabelDynamicHeight.m

#import "UILabel+UILabelDynamicHeight.h"
@implementation UILabel (UILabelDynamicHeight)

#pragma mark - Berechnen der Größe, Grenzen, Rahmen des mehrzeiligen Labels
/*====================================================================*/

/* Berechnen der Größe, der Grenzen, des Rahmens des mehrzeiligen Labels */

/*====================================================================*/
/**
 *  Gibt die Größe des Labels zurück
 *
 *  @param aLabel Zur Berechnung der Höhe zu verwenden
 *
 *  @return Größe des Labels
 */
-(CGSize)sizeOfMultiLineLabel{

    //Label Text
    NSString *aLabelTextString = [self text];

    //Label Schriftart
    UIFont *aLabelFont = [self font];

    //Breite des Labels
    CGFloat aLabelSizeWidth = self.frame.size.width;

    if (SYSTEM_VERSION_LESS_THAN(iOS7_0)) {
        //Version < 7.0

        return [aLabelTextString sizeWithFont:aLabelFont
                            constrainedToSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
                                lineBreakMode:NSLineBreakByWordWrapping];
    }
    else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(iOS7_0)) {
        //Version >= 7.0

        //Gibt die berechnete Größe des Labels zurück
        return [aLabelTextString boundingRectWithSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
                                              options:NSStringDrawingUsesLineFragmentOrigin
                                           attributes:@{
                                                        NSFontAttributeName : aLabelFont
                                                        }
                                              context:nil].size;

    }

    return [self bounds].size;

}
@end

56voto

Filip Radelic Punkte 26548

Wenn Sie -sizeToFit auf einer UILabel-Instanz aufrufen, wird sie automatisch auf die Größe des angezeigten Textes angepasst, ohne dass eine Berechnung erforderlich ist. Wenn Sie die Größe benötigen, können Sie sie nachher aus der frame-Eigenschaft des Labels erhalten.

label.numberOfLines = 0; // erlaubt dem Label, so viele Zeilen wie nötig zu haben
label.text = @"ein langer Text";
[label sizeToFit];
NSLog(@"Die Rahmen des Labels sind: %@", NSStringFromCGRect(label.frame));

37voto

kgaidis Punkte 12126

Zusammenfassend lässt sich die Höhe eines Labels berechnen, indem man den String verwendet und boundingRectWithSize aufruft. Sie müssen die Schriftart als Attribut angeben und .usesLineFragmentOrigin für mehrzeilige Labels hinzufügen.

let labelWidth = label.frame.width
let maxLabelSize = CGSize(width: labelWidth, height: CGFloat.greatestFiniteMagnitude)
let actualLabelSize = label.text!.boundingRect(with: maxLabelSize, options: [.usesLineFragmentOrigin], attributes: [.font: label.font], context: nil)
let labelHeight = actualLabelSize.height(withWidth:labelWidth)

Einige Erweiterungen, um genau das zu tun:

Swift-Version:

extension UILabel {
    func textHeight(withWidth width: CGFloat) -> CGFloat {
        guard let text = text else {
            return 0
        }
        return text.height(withWidth: width, font: font)
    }

    func attributedTextHeight(withWidth width: CGFloat) -> CGFloat {
        guard let attributedText = attributedText else {
            return 0
        }
        return attributedText.height(withWidth: width)
    }
}

extension String {
    func height(withWidth width: CGFloat, font: UIFont) -> CGFloat {
        let maxSize = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
        let actualSize = self.boundingRect(with: maxSize, options: [.usesLineFragmentOrigin], attributes: [.font : font], context: nil)
        return actualSize.height
    }
}

extension NSAttributedString {
    func height(withWidth width: CGFloat) -> CGFloat {
        let maxSize = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
        let actualSize = boundingRect(with: maxSize, options: [.usesLineFragmentOrigin], context: nil)
        return actualSize.height
    }
}

Objective-C-Version:

UILabel+Utility.h

#import 
@interface UILabel (Utility)
- (CGFloat)textHeightForWidth:(CGFloat)width;
- (CGFloat)attributedTextHeightForWidth:(CGFloat)width;
@end

UILabel+Utility.m

@implementation NSString (Utility)
- (CGFloat)heightForWidth:(CGFloat)width font:(UIFont *)font {
    CGSize maxSize = CGSizeMake(width, CGFLOAT_MAX);
    CGSize actualSize = [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil].size;
    return actualSize.height;
}
@end

@implementation NSAttributedString (Utility)
- (CGFloat)heightForWidth:(CGFloat)width {
    CGSize maxSize = CGSizeMake(width, CGFLOAT_MAX);
    CGSize actualSize = [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
    return actualSize.height;
}
@end

@implementation UILabel (Utility)
- (CGFloat)textHeightForWidth:(CGFloat)width {
    return [self.text heightForWidth:width font:self.font];
}
- (CGFloat)attributedTextHeightForWidth:(CGFloat)width {
    return [self.attributedText heightForWidth:width];
}
@end

17voto

Infinity James Punkte 4629

Die aktuelle Lösung wurde ab iOS 7 verworfen.

Hier ist eine aktualisierte Lösung:

+ (CGFloat)heightOfCellWithIngredientLine:(NSString *)ingredientLine
                       withSuperviewWidth:(CGFloat)superviewWidth
{
    CGFloat labelWidth                  = superviewWidth - 30.0f;
    //    Verwenden Sie die bekannte Label-Breite mit einer maximalen Höhe von 100 Punkten
    CGSize labelContraints              = CGSizeMake(labelWidth, 100.0f);

    NSStringDrawingContext *context     = [[NSStringDrawingContext alloc] init];

    CGRect labelRect                    = [ingredientLine boundingRectWithSize:labelContraints
                                                        options:NSStringDrawingUsesLineFragmentOrigin
                                                     attributes:nil
                                                        context:context];

    //    Geben Sie die berechnete erforderliche Höhe der Zelle unter Berücksichtigung des Labels zurück
    return labelRect.size.height;
}

Der Grund, warum meine Lösung so eingerichtet ist, liegt darin, dass ich eine UITableViewCell verwende und die Zelle dynamisch entsprechend dem Platzbedarf des Labels anpassen möchte.

9voto

AlexKoren Punkte 1605

Ohne sizeToFit aufzurufen, können Sie dies alles numerisch mit einer sehr einfachen Lösung machen:

+ (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;
}

Ich benutze es oft für UITableViewCells, die dynamisch zugewiesene Höhen haben.

Löst auch das Problem der Attribute, @Salman Zaidi.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X