Je voudrais ajouter mes réflexions car j'avais exactement le même problème.
J'utilisais UITextView
car il avait un meilleur alignement du texte (justifiez, qui à l'époque n'était pas disponible dans UILabel
), mais afin de "simuler" non-interactif-non-défilable UILabel
, je désactivais complètement le défilement, le rebond et l'interaction de l'utilisateur .
Bien sûr, le problème était que le texte était dynamique et, bien que la largeur soit fixe, la hauteur devrait être recalculée chaque fois que je définissais une nouvelle valeur de texte.
boundingRectWithSize
Cela ne fonctionnait pas du tout pour moi, d'après ce que je pouvais voir, UITextView
ajoutait une marge sur le dessus qui boundingRectWithSize
n'entrerait pas dans un décompte, par conséquent, la hauteur récupérée boundingRectWithSize
était plus petite qu'elle ne devrait l'être.
Étant donné que le texte ne devait pas être mis à jour rapidement, il est simplement utilisé pour certaines informations qui peuvent être mises à jour toutes les 2-3 secondes au maximum, j'ai décidé de l'approche suivante:
/* 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 );
}
* Le code ci-dessus n'est pas directement copié à partir de ma source, j'ai dû l'ajuster / le supprimer d'un tas d'autres éléments non nécessaires pour cet article. Ne le prenez pas pour copier-coller-et-cela-fonctionnera-code.
L'inconvénient évident est qu'il a l'allocation et la libération, pour chaque appel.
Mais l'avantage est que vous évitez de dépendre de la compatibilité entre la façon dont boundingRectWithSize dessine le texte et calcule sa taille et l'implémentation du dessin de texte dans UITextView
(ou UILabel
que vous pouvez également utiliser simplement remplacer UITextView
par UILabel
). Tous les «bogues» qu'Apple pourrait avoir sont ainsi évités.
PS Il semblerait que vous ne devriez pas avoir besoin de ce "temp" UITextView
et que vous pouvez simplement demander sizeThatFits
directement à la cible, mais cela n'a pas fonctionné pour moi. Bien que la logique dirait que cela devrait fonctionner et que l'allocation / la libération de temporaires UITextView
ne sont pas nécessaires, ce n'est pas le cas. Mais cette solution fonctionnait parfaitement pour tout texte que je mettrais en place.
lineBreakMode
?