web-dev-qa-db-fra.com

Calcul de la hauteur du texte multiligne pour UILabel / UITableViewCell: résultats différents lors du calcul par rapport au dessin réel

Ce sujet général a été posé ici plusieurs fois: comment rendre UITableViewCells avec une quantité variable de texte et donc une hauteur variable. La réponse canonique est: vous calculez la hauteur dans le délégué du contrôleur de vue de table dans heightForRowAtIndexPath en utilisant sizeWithFont: constrainedToSize: lineBreakMode :. Plus tard, la cellule est dessinée et vous utilisez quelque chose comme [label sizeToFit] si nécessaire, et tout fonctionne comme par magie.

Mon problème: j'obtiens un habillage pour certaines cellules car sizeWithFont: renvoie différentes dimensions à partir du dessin réel.

Un exemple précis:

Le texte est le suivant: "Les gens oublient que @BillGates avait une ardoise sexy de 1/4 pouce d'épaisseur en 1993 de NEC. Quoi qu'il arrive cette semaine ne sera PAS une question de matériel!"

CGSize theSize = [text sizeWithFont:[UIFont systemFontOfSize:17.0f] constrainedToSize:CGSizeMake(310.0f, FLT_MAX) lineBreakMode:UILineBreakModeWordWrap];
NSLog(@"calculated size for %@: %f, %f",text, theSize.width, theSize.height);

Cela renvoie: 306.000000, 84.000000. (C'est-à-dire 4 lignes avec une police de 17 pixels et un espacement de lignes de 4 pixels, interligne de 21 pixels.) Bon.

Cependant, plus tard lors du dessin de la cellule:

label = (UILabel *)[cell viewWithTag:3];
label.text = [NSString stringWithFormat:@"%@", text];
label.lineBreakMode = UILineBreakModeWordWrap;
label.font = [UIFont systemFontOfSize:17.0f];
CGSize labelSize;   
labelSize = label.frame.size;
NSLog(@"label size before resizing: %f, %f", labelSize.width, labelSize.height);
[label sizeToFit];
labelSize = label.frame.size;
NSLog(@"label size after resizing: %f, %f for text %@", labelSize.width, labelSize.height,text);

(UILabel est chargé dans le cadre de UITableViewCell à partir de NIB. Dans IB, je l'ai défini à 310 pixels de large.)

Cela devrait retourner exactement la même taille que ci-dessus. Au lieu de cela, j'obtiens 281.000000, 105.000000 comme dimensions après l'appel de sizeToFit. Il y a maintenant 5 lignes au moment du dessin au lieu de 4, et le texte déborde, je vois le débordement dans l'interface utilisateur.

Donc, pour le même texte, je fais calculer deux dimensions différentes et je ne peux pas le comprendre. Est-ce quelque chose sur UILabel? At-il des marges intérieures? Cela continue de se produire pour certains textes mais pas pour d'autres, et je ne l'ai pas attribué à quelque chose de particulier au sujet des cordes; semble aléatoire. Cette rubrique souligne qu'il existe deux passes de traitement: le calcul de la hauteur par rapport au dessin réel. Cela correspond à ce que je vois. Mais je ne comprends pas exactement ce qui se passe ni comment y remédier.

La question: pourquoi est-ce que je vois deux tailles calculées différentes et comment puis-je le corriger?

39
Jaanus

Bien sûr, la solution est évidente secondes après la publication. Peut-être aussi utile aux autres ...

La taille par sizeWithFont: était correct. Les tailles que j'ai calculées de la manière ci-dessus étaient incorrectes, car [label sizeToFit] réduit la largeur du cadre de l'étiquette. Lors des appels suivants au même code, il a commencé avec la trame qui avait peut-être déjà été réduite.

Le correctif consistait simplement à réinitialiser le cadre width à une bonne largeur connue avant de dimensionner pour l'adapter:

CGRect labelFrame = label.frame;
labelFrame.size.width = 310;
label.frame = labelFrame;
[label sizeToFit];
36
Jaanus

Pour les étiquettes multilignes, vous devez définir

cell.textLabel.numberOfLines = 0;

puis

[cell.textLabel sizeToFit];

Mais pour une jolie vue, vous devez ajouter quelques pixels de remplissage. Et votre application sera géniale!

12
Oleg
 titleSize = [title sizeWithFont:[UIFont systemFontOfSize:(CGFloat)17.0]
                                constrainedToSize:CGSizeMake(280, 2000)
                                    lineBreakMode:NSLineBreakByWordWrapping];
6
Aswathi