2009-07-30 16 views
5

Próbuję zmierzyć wizualny rozmiar NSString, który bierze pod uwagę liczbę linii, które mogę renderować. Jednak sizeWithFont nie uwzględnia właściwości numberOfLines? Tak więc mój algorytm układania pozycjonuje wszystko, co jest niższe, niż musi być.iPhone UILabel sizeWithFont:

_price = [[UILabel alloc] init]; 
_price.text = myPriceValue; 
_price.lineBreakMode = UILineBreakModeWordWrap; 
_price.numberOfLines = 3; 
_price.backgroundColor = [UIColor clearColor]; 
_price.textColor = TTSTYLEVAR(colorPrice); 
/// the follow code ignores numberOfLines and just tells me the size of the whole block. 
// I'd like it to be aware of numberOfLines 
// 
CGSize priceSize = [_price.text sizeWithFont:_price.font 
     constrainedToSize:CGSizeMake(maxWidth, CGFLOAT_MAX) 
     lineBreakMode:UILineBreakModeWordWrap]; 

Czy ktoś wie, jak to zrobić, korzystając z iPhone SDK?

Odpowiedz

12

Zamiast CGFLOAT_MAX do max wysokości obliczeniach tekst, spróbuj coraz rozmiaru jednej linii z tego:

[_price.text sizeWithFont:_price.font].height 

a następnie mnożąc to przez maksymalną # wierszy, które chcesz, a następnie podłączyć to pod wysokość, do której się ograniczasz. Byłoby prawdopodobnie wyglądać następująco:

_price = [[UILabel alloc] init]; 
_price.text = myPriceValue; 
_price.lineBreakMode = UILineBreakModeWordWrap; 
_price.numberOfLines = 3; 
_price.backgroundColor = [UIColor clearColor]; 
_price.textColor = TTSTYLEVAR(colorPrice); 
CGFloat lineHeight = [_price.text sizeWithFont:_price.font].height; 
CGSize priceSize = [_price.text sizeWithFont:_price.font 
     constrainedToSize:CGSizeMake(maxWidth, lineHeight * _price.numberOfLines) 
     lineBreakMode:UILineBreakModeWordWrap]; 

Nie używaj tego jeśli kiedykolwiek ustawić liczbę wierszy do 0 jako maksymalna wysokość wyniesie 0 w tym przypadku; powinieneś wtedy użyć CGFLOAT_MAX.

+2

sizeWithFont jest przestarzałe w iOS7 i zamiast tego należy użyć boundingReadWithSize. –

-1

Oczywiście nie bierze tego pod uwagę, ponieważ nic nie jest wywoływane ani przekazywane. Pracujesz ściśle nad ciągami, rozmiarami i czcionkami. To etykieta zawiera liczbę linii.

Nie jestem pewien, jaki jest dokładnie twój problem; dostajesz rozmiar, który jest zbyt wysoki lub za krótki, lub co? Możesz sprawdzić liczbę linii tekstu, dzieląc wysokość wyniku przez wysokość czcionki, która jest wartością wznoszącego się plus wznoszenia, jak sądzę.

+0

Właściwie sizeWithFont: constainedToSize: lineBreakMode uwzględnia obwiednię i zawijanie. Należy zauważyć, że sizeWithFont: forWidth: lineBreakMode NIE działa z wieloma wierszami. –

0

Zamiast próbować to zrobić w jednej rozmowy, coś jak to zrobić (za przeproszeniem Pseudokod, jest późno):

NSString *s = _price.text; 
UIFont *font = _price.font; 
CGFloat fontSize = font.pointSize; 

while (TRUE) 
{ 
    CGSize priceSize = [s sizeWithFont: font constrainedToSize: 
     CGSizeMake(maxWidth, fontSize) lineBreakMode: UILineBreakModeWordWrap]; 

    if (/* priceSize is satisfactory */) 
    { 
     break; // Make sure this exits, eventually!!! 
    } 
    fontSize -= 1.0; // or a smaller decrement if you like 
    font = // new, smaller font 

} 
0

Poprawną odpowiedzią jest, oczywiście, trzeba ustawić numberOfLines 0, co sprawi, że framework obliczy wynik przy użyciu wielu linii. Zobacz także this question.

+0

Nie, liczba linii do 0 to nieskończone linie. ale chcę wysokości 3 linii – CVertex

+0

Ah, widzę. Źle zrozumiałem pytanie. –

5

Użyj rozmiaru sizeToFit UILabel zamiast sizeWithFont: aby ułożyć wieloliniowy kod UILabel, ponieważ sizeWithFont: spowoduje obcięcie ciągu znaków (patrz dokumentacja w języku Apple). Poniższy kod zmniejsza rozmiar czcionki etykiety aż do tekstu zmieścić w określonym rozmiarze ... wielu wierszy tekstu będzie używany jak tylko pasuje do określonej wysokości:

-(void)setFontSizeOfMultiLineLabel: (UILabel*)label 
     toFitSize: (CGSize) size 
     forMaxFontSize: (CGFloat) maxFontSize 
     andMinFontSize: (CGFloat) minFontSize 
     startCharacterWrapAtSize: (CGFloat)characterWrapSize{ 

CGRect constraintSize = CGRectMake(0, 0, size.width, 0); 
label.frame = constraintSize; 
label.lineBreakMode = UILineBreakModeWordWrap; 
label.numberOfLines = 0; // allow any number of lines 

for (int i = maxFontSize; i > minFontSize; i--) { 

    if((i < characterWrapSize) && (label.lineBreakMode == UILineBreakModeWordWrap)){ 
     // start over again with lineBreakeMode set to character wrap 
     i = maxFontSize; 
     label.lineBreakMode = UILineBreakModeCharacterWrap; 
    } 

    label.font = [label.font fontWithSize:i]; 
    [label sizeToFit]; 
    if(label.frame.size.height < size.height){ 
     break; 
    }  
    label.frame = constraintSize; 
    } 
} 

nazywają to z etykieta, która ma swój ulubiony tekst i czcionki:

UILabel *label = [[UILabel alloc] initWithFrame: CGRectZero]; 
label.backgroundColor = [UIColor clearColor]; 
label.textColor = [UIColor whiteColor]; 
label.text = text; 
label.font = [UIFont fontWithName: @"Helvetica" size: 16]; 
[self setFontSizeOfMultiLineLabel: label toFitSize: CGSizeMake(200, 44) forMaxFontSize: 16 andMinFontSize: 8 startCharacterWrapAtSize: 11]; 

parametr startCharacterWrapAtSize pozwala zdecydować się na stosowanie characterWrap począwszy od dając rozmiaru czcionki. To powinno zaoszczędzić miejsce w przypadku, gdyby słowoWrap używałoby naprawdę małych czcionek.

edit: bugfix

+0

To również działałoby dobrze jako kategoria w 'UILabel' –