2010-11-13 20 views
39

Wyświetlałem tekst w UILabel za pomocą metody wrap. Teraz chcę znaleźć numer linii w UILabel.Jak znaleźć liczbę linii UILabel

Jeśli istnieje jakikolwiek sposób na znalezienie liczby wierszy UILabel.

Dzięki.

+0

http://stackoverflow.com/questions/4082041/resulting-lines-of-uilabel-with-uilinebreakmodewordwrap/14401282#14401282 – TheTiger

Odpowiedz

50

Jak wskazano, ten post dotyczy sposobu uzyskania wysokości, a nie liczby linii. Aby uzyskać liczbę linii, należy uzyskać wysokość pojedynczej litery, np.

  1. @"A".
  2. Podziel wysokość struny według wysokości otrzymanej w 1 powyżej.

E.g.

CGFloat unitHeight = [@"A" heightForWidth:width usingFont:font]; 
CGFloat blockHeight = [text heightForWidth:width usingFont:font]; 
NSInteger numberOfLines =  ceilf(blockHeight/unitHeight); 
// need to #include <math.h> for ^^^^^ 

Jako iOS 7 drodze uzyskanie etykiety pożądaną wysokość zmieniło. Aby uzyskać wysokość, można użyć następującego kodu:

gdzie wysokość jest r.size.height. Należy podać font. Możesz umieścić to w kategorii dla NSString dla wygody, np.

@implementation NSString (HeightCalc) 

- (CGFloat)heightForWidth:(CGFloat)width usingFont:(UIFont *)font 
{ 
    NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init]; 
    CGSize labelSize = (CGSize){width, FLT_MAX}; 
    CGRect r = [self boundingRectWithSize:labelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: font} context:context]; 
    return r.size.height; 
} 

@end 

(Czy zarządzanie pamięcią, jeśli nie za pomocą łuku, btw.)

Dla iOS 6 i poniżej:

Powiedzmy masz UILabel *myLabel i chcesz dowiedzieć się wysokość etykieta (z pewnymi poprawkami, możesz uzyskać # linii dzieląc wysokość z odpowiednią liczbą, która zależy od rozmiaru czcionki).

UILabel *myLabel; 
CGSize labelSize = [myLabel.text sizeWithFont:myLabel.font 
          constrainedToSize:myLabel.frame.size 
           lineBreakMode:UILineBreakModeWordWrap]; 
CGFloat labelHeight = labelSize.height; 

Nadzieję, że pomaga. Jeśli to nie zadziała, daj mi znać, a przekopię się dalej. Również nietestowany kod, ale działał z referencji.

Pełniejszy przykład, tutaj jest kod, który umieścić w viewDidLoad: metoda kontrolera widoku:

[super viewDidLoad]; 
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50,50,200,350)]; 
myLabel.numberOfLines = 0; 
myLabel.lineBreakMode = UILineBreakModeWordWrap; 
myLabel.text = @"This is some text in a UILabel which is long enough to wrap around the lines in said UILabel. This is a test, this is only a test."; 
[self.view addSubview:myLabel]; 
CGSize labelSize = [myLabel.text sizeWithFont:myLabel.font 
          constrainedToSize:myLabel.frame.size 
           lineBreakMode:UILineBreakModeWordWrap]; 
CGFloat labelHeight = labelSize.height; 
NSLog(@"labelHeight = %f", labelHeight); 
[myLabel release]; 

Wyjście z NSLog idzie:

2010-11-15 18:25:27.817 so_labelheight[728:307] labelHeight = 126.000000 
+0

pokazuje następujące dwa błędy // błąd: niekompatybilny typ dla argumentu 2 z "sizeWithFont: constrainedToSize : lineBreakMode:” \t \t \t błąd: żądanie członka«rozmiar»w coś nie struktury lub unii – Velmurugan

+0

Oczywiście .size nie jest właściwością na UILabel, ale powinno to prawdopodobnie coś myLabel.frame.size lub myLabel .bounds.size (nie wiesz, który z nich chcesz). –

+0

Ach tak, tęskniłem za tym. Dzięki Wim H. Naprawiono powyższy przykład, aby użyć frame.size. – Kalle

7

Sposób -sizeWithFont:constrainedToSize:lineBreakMode jest teraz przestarzałe. Będziesz teraz chciał użyć metody -boundingRectWithSize:options:attributes:context:.

Oto przykłady:

CGSize boundingRectSize = CGSizeMake(widthToConstrainTo, CGFLOAT_MAX); 
NSDictionary *attributes = @{NSFontAttributeName : [UIFont fontWithName:fontName size:14]}; 
CGRect labelSize = [labelString boundingRectWithSize:boundingRectSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading 
               attributes:attributes 
                context:nil]; 

W powyższym przykładzie wiem szerokość Chcę ograniczyć etykietę, ale ponieważ nie jestem pewien co do wysokości, po prostu max wysokość param z wykorzystaniem CGFLOAT_MAX . W przypadku modelu options należy użyć wartości NSStringDrawingUsesLineFragmentOrigin i NSStringDrawingUsesFontLeading, jeśli próbujesz obliczyć rozmiar etykiety, która może być dowolną liczbą linii.

6

sizeWithFont jest przestarzałe w iOS 7, można użyć zamiast tego:

- (int)lineCountForText:(NSString *) text 
{ 
    UIFont *font = ... 

    CGRect rect = [text boundingRectWithSize:CGSizeMake(200, MAXFLOAT) 
            options:NSStringDrawingUsesLineFragmentOrigin 
            attributes:@{NSFontAttributeName : font} 
            context:nil]; 

    return ceil(rect.size.height/font.lineHeight); 
} 
13

Dla iOS7 i powyżej, officially sanctioned way policzyć liczbę linii jest użycie TextKit:

func numberOfLinesForString(string: String, size: CGSize, font: UIFont) -> Int { 
    let textStorage = NSTextStorage(string: string, attributes: [NSFontAttributeName: font]) 

    let textContainer = NSTextContainer(size: size) 
    textContainer.lineBreakMode = .ByWordWrapping 
    textContainer.maximumNumberOfLines = 0 
    textContainer.lineFragmentPadding = 0 

    let layoutManager = NSLayoutManager() 
    layoutManager.textStorage = textStorage 
    layoutManager.addTextContainer(textContainer) 

    var numberOfLines = 0 
    var index = 0 
    var lineRange : NSRange = NSMakeRange(0, 0) 
    for (; index < layoutManager.numberOfGlyphs; numberOfLines++) { 
     layoutManager.lineFragmentRectForGlyphAtIndex(index, effectiveRange: &lineRange) 
     index = NSMaxRange(lineRange) 
    } 

    return numberOfLines 
} 
2

(Pierwotnie opublikowałem moją odpowiedź: here, ale nie mam wystarczającej reputacji, aby komentować lub oznaczać duplikaty.)

Pozostałe odpowiedzi I'v e znalezione nie szanują własność UILabelnumberOfLines gdy jest on ustawiony na wartość inną niż 0.

Oto kolejny opcji można dodać do danej kategorii lub podklasy:

- (NSUInteger)lineCount 
{ 
    CGSize size = [self sizeThatFits:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)]; 
    return MAX((int)(size.height/self.font.lineHeight), 0); 
} 

Kilka uwag:

  • Używam tego na UILabel z przypisanym tekstem, nigdy nawet nie ustawiając właściwości font i działa poprawnie. Oczywiście natknąłbyś się na problemy, gdybyś używał wielu czcionek w swoim attributedText.
  • Jeśli instacji UILabel mieć wypustki zwyczaj krawędź (na przykład poprzez nadpisanie drawTextInRect:, co jest miłe sztuczka znalazłem here), trzeba pamiętać, aby wziąć pod uwagę te wypustki przy obliczaniu size powyżej. Na przykład: CGSizeMake(self.frame.size.width - (self.insets.left + self.insets.right), CGFLOAT_MAX)
5

Jeśli szukasz tej odpowiedzi w Swift 2 +/iOS 8, to będzie wyglądać następująco:

func numberOfLinesInLabel(yourString: String, labelWidth: CGFloat, labelHeight: CGFloat, font: UIFont) -> Int { 

    let paragraphStyle = NSMutableParagraphStyle() 
    paragraphStyle.minimumLineHeight = labelHeight 
    paragraphStyle.maximumLineHeight = labelHeight 
    paragraphStyle.lineBreakMode = .ByWordWrapping 

    let attributes: [String: AnyObject] = [NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraphStyle] 

    let constrain = CGSizeMake(labelWidth, CGFloat(Float.infinity)) 

    let size = yourString.sizeWithAttributes(attributes) 
    let stringWidth = size.width 

    let numberOfLines = ceil(Double(stringWidth/constrain.width)) 

    return Int(numberOfLines) 
} 
+0

Ta odpowiedź jest dobra od iOS8 –

+0

Dzięki @AvielGross. Edytowane w celu odzwierciedlenia danych wejściowych. – cph2117

+0

Jaki jest cel "ograniczenia" tutaj? –

0
func getHeight(text: NSString, width:CGFloat, font: UIFont) -> CGFloat 
{ 
    let rect = text.boundingRect(with: CGSize.init(width: width, height: CGFloat.greatestFiniteMagnitude), options: ([NSStringDrawingOptions.usesLineFragmentOrigin,NSStringDrawingOptions.usesFontLeading]), attributes: [NSFontAttributeName:font], context: nil) 
    return rect.size.height 
} 

tekst: Etykieta którego wysokość trzeba znaleźć z danym ciągiem

width: szerokość UILabel

czcionki: czcionka UILabel za

Powiązane problemy