Chciałbym dodać swoje przemyślenia, ponieważ miałem dokładnie ten sam problem.
Używałem, UITextView
ponieważ miał ładniejsze wyrównanie tekstu (justowanie, które w tamtym czasie nie było dostępne UILabel
), ale w celu „symulacji” nieinteraktywnego, nieprzewijalnegoUILabel
, całkowicie wyłączyłem przewijanie, odbijanie i interakcję z użytkownikiem .
Oczywiście problem polegał na tym, że tekst był dynamiczny i chociaż szerokość byłaby stała, wysokość powinna być przeliczana za każdym razem, gdy ustawiam nową wartość tekstu.
boundingRectWithSize
w ogóle nie działało dobrze, z tego, co widziałem, UITextView
dodawało trochę marginesu na górze, który boundingRectWithSize
nie mógł się liczyć, stąd pobrana wysokość boundingRectWithSize
była mniejsza niż powinna.
Ponieważ tekst nie miał być aktualizowany szybko, jest używany tylko do niektórych informacji, które mogą być aktualizowane najczęściej co 2-3 sekundy, zdecydowałem się na następujące podejście:
/* This f is nested in a custom UIView-inherited class that is built using xib file */
-(void) setTextAndAutoSize:(NSString*)text inTextView:(UITextView*)tv
{
CGFloat msgWidth = tv.frame.size.width; // get target's width
// Make "test" UITextView to calculate correct size
UITextView *temp = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, msgWidth, 300)]; // we set some height, really doesn't matter, just put some value like this one.
// Set all font and text related parameters to be exact as the ones in targeted text view
[temp setFont:tv.font];
[temp setTextAlignment:tv.textAlignment];
[temp setTextColor:tv.textColor];
[temp setText:text];
// Ask for size that fits :P
CGSize tv_size = [temp sizeThatFits:CGSizeMake(msgWidth, 300)];
// kill this "test" UITextView, it's purpose is over
[temp release];
temp = nil;
// apply calculated size. if calcualted width differs, I choose to ignore it anyway and use only height because I want to have width absolutely fixed to designed value
tv.frame = CGRectMake(tv.frame.origin.x, tv.frame.origin.y, msgWidth, tv_size.height );
}
* Powyższy kod nie jest bezpośrednio kopiowany z mojego źródła, musiałem go dostosować / wyczyścić z wielu innych rzeczy, które nie są potrzebne w tym artykule. Nie bierz tego za kod kopiuj-wklej i zadziała.
Oczywistą wadą jest to, że ma on przydzielanie i zwalnianie dla każdego połączenia.
Ale zaletą jest to, że unikasz zależności od zgodności między sposobem, w jaki boundingRectWithSize rysuje tekst i oblicza jego rozmiar, a implementacją rysowania tekstu w UITextView
(lub UILabel
które również można użyć po prostu zastąpić UITextView
z UILabel
). W ten sposób można uniknąć wszelkich „błędów”, które może mieć Apple.
PS Wydawałoby się, że nie powinieneś potrzebować tego "temp" UITextView
i możesz po prostu zapytać sizeThatFits
bezpośrednio od celu, jednak to nie zadziałało dla mnie. Chociaż logika powiedziałaby, że powinno działać, a przydzielanie / zwalnianie tymczasowych UITextView
nie jest potrzebne, tak się nie stało. Ale to rozwiązanie działało bezbłędnie dla każdego tekstu, który bym wstawił.
lineBreakMode
?