2009-01-18 4 views
37

Dans ma question "How do I get -[NSString sizeWithFont:forWidth:lineBreakMode:] to work?", j'ai appris que -[NSString sizeWithFont:constrainedToSize:lineBreakMode:] était réellement ce dont j'avais besoin.Qu'est-ce que - [NSString sizeWithFont: forWidth: lineBreakMode:] bon?

La documentation relative aux états -[NSString sizeWithFont:forWidth:lineBreakMode:] explique que le texte n'est pas enroulé sur des lignes supplémentaires. Alors, comment pourrais-je l'utiliser? (Des exemples aideraient.)

Répondre

66

Cela fonctionne également très bien pour les chaînes multilignes.

Fondamentalement, c'est une fonction qui vous permet de voir la taille d'une chaîne lorsqu'elle est rendue avec un mode de police et de saut de ligne.

Je l'utilise dans quelques endroits de mon application quand j'ai un texte de longueur variable que je veux afficher dans une certaine zone.

Par défaut, un UILabel centre le texte verticalement. Pour que le texte soit aligné au mieux, vous devez redimensionner l'étiquette pour n'être que la hauteur requise par la chaîne qui s'y trouve.

J'utilise cette méthode pour cela.

Et exemple de la façon dont je l'utiliser pour le faire est la suivante:

//Calculate the expected size based on the font and linebreak mode of your label 
CGSize maximumLabelSize = CGSizeMake(296,9999); 

CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font 
         constrainedToSize:maximumLabelSize 
         lineBreakMode:yourLabel.lineBreakMode]; 

//adjust the label the the new height. 
CGRect newFrame = yourLabel.frame; 
newFrame.size.height = expectedLabelSize.height; 
yourLabel.frame = newFrame; 

Vous indiquez la taille d'une zone que vous devez mettre le texte, et cette méthode vous indique la quantité d'espace il prendra (emballage au besoin). Aussi, si la chaîne dépasse les limites du rectangle que vous fournissez, vous pouvez dire et ensuite décider comment afficher le texte.

La référence à ce n'est pas réellement envelopper le texte est là parce que cette méthode ne fait réellement rien au texte. Il se contente de l'énoncer virtuellement et renvoie la taille d'une zone dont il aurait besoin pour l'exposer.

est la responsabilité de l'étiquette (ou du conteneur que vous utilisez pour le texte) pour effectuer l'emballage/quoi que ce soit d'autre qui doit être fait.

Espérons que ça aide.

chris.

+0

newFrame.size.height = taille maximale d'étiquette .height; SB: newFrame.size.height = expectedLabelSize.height; – JoBu1324

+0

fonctionne même lorsque vous dessinez dans un rect! – tipycalFlow

2

Il semblerait que ce serait bon pour les étiquettes à une seule ligne. Par exemple, si vous dessinez une chaîne qui peut être tronquée ou un saut de ligne, mais vous ne dessinerez pas plus d'une ligne. Il peut toujours être utile de connaître la hauteur et la largeur exactes de la chaîne, de sorte que vous puissiez la positionner exactement où vous le souhaitez (et dessiner d'autres éléments de l'interface utilisateur autour d'elle).

25

Pendant un moment, j'ai pensé que cette routine était simplement brisée. Il semble que c'est la routine parfaite pour travailler comment haut un morceau de texte est, lorsqu'il est emballé à une certaine largeur. Cependant ce n'est pas ce qu'il fait. En effet, la hauteur retournée est toujours une seule ligne. (Ce qui ne sert à rien, soit dit en passant. UIFont « s -leading renvoie la même valeur)

Pour citer la documentation au moment de la rédaction:

Bien qu'il calcule où les sauts de ligne se produiraient, cette méthode ne fonctionne pas envelopper le texte dans des lignes supplémentaires; [...]

Cette phrase m'a embrouillé pendant longtemps.Mes pensées étaient les suivantes:

  • Calcul des sauts de ligne, mais pas de l'emballage. Eh?
  • Peut-être qu'ils signifient que le récepteur NSString lui-même ne sera pas muté pour refléter les sauts de ligne? Mais je ne m'attends pas à ça de toute façon?
  • Cette phrase n'est pas cohérente avec elle-même. Je n'ai pas d'autre choix que de l'ignorer.

Cependant, il s'avère qu'il existe une signification qui correspond au comportement que nous voyons. Il semble que ce qu'ils veulent dire est:

Cette routine va calculer où la première ligne -break se produira, et tout le texte après cela est ignoré aux fins du calcul du cadre de sélection.

La boîte de sélection retournée aura donc la hauteur d'une ligne et une largeur jusqu'au maximum spécifié. (La largeur peut être inférieure selon l'endroit où le saut de ligne est calculé ou si le texte est suffisamment court pour ne pas avoir besoin de la largeur maximale.)

Pour répondre à la question actuelle: Qu'est-ce que c'est bon? pour? Je n'ai rien trouvé d'utile moi-même: seulement des choses où je pensais que ce serait utile, mais ce n'était pas le cas. Certaines choses qui viennent à l'esprit, cependant, sont:

  • Centrer un morceau de texte d'une seule ligne. Je pense à des boutons et/ou des titres ici. (Bien que UILabel et UIButton peuvent le faire, parfois vous voulez le dessiner vous-même.)
  • Calcul des limites pour un "extrait" d'un texte plus long. Ici, je pense à l'endroit où vous pourriez vouloir montrer un extrait d'un texte beaucoup plus grand.
+2

+1 pour la question brutalement honnête "à quoi ça sert?" Oui j'ai eu la même pensée. Quoi qu'il en soit, ça sonne comme NSString sizeWithFont: constrainedToSize: lineBreakMode est ce dont j'ai besoin. Merci – Chris

1

est ici quelque chose que je suis venu avec après l'application de quelques principes de l'exemple de PyjamaSam:

AnnotationPin *myAnnotation = (AnnotationPin *)annotation; 

self = [super initWithAnnotation:myAnnotation reuseIdentifier:reuseIdentifier]; 
self.backgroundColor = [UIColor greenColor]; 
self.frame = CGRectMake(0,0,30,30); 
imageView = [[UIImageView alloc] initWithImage:myAnnotation.THEIMAGE]; 
imageView.frame = CGRectMake(3,3,20,20); 
imageView.layer.masksToBounds = NO; 
[self addSubview:imageView]; 
[imageView release]; 

CGSize titleSize = [myAnnotation.THETEXT sizeWithFont:[UIFont systemFontOfSize:12]]; 
CGRect newFrame = self.frame; 
newFrame.size.height = titleSize.height + 12; 
newFrame.size.width = titleSize.width + 32; 
self.frame = newFrame; 
self.layer.borderColor = [UIColor colorWithRed:0 green:.3 blue:0 alpha:1.0f].CGColor; 
self.layer.borderWidth = 3.0; 

UILabel *infoLabel = [[UILabel alloc] initWithFrame:CGRectMake(26,5,newFrame.size.width-32,newFrame.size.height-12)]; 
infoLabel.text = myAnnotation.title; 
infoLabel.backgroundColor = [UIColor clearColor]; 
infoLabel.textColor = [UIColor blackColor]; 
infoLabel.textAlignment = UITextAlignmentCenter; 
infoLabel.font = [UIFont systemFontOfSize:12]; 

[self addSubview:infoLabel]; 
[infoLabel release]; 

Dans cet exemple, j'ajoute une épingle personnalisée à une classe MKAnnotation qui redimensionne un UILabel selon la taille du texte. Il ajoute également une image sur le côté gauche de la vue, de sorte que vous voyez une partie du code gérant l'espacement approprié pour gérer l'image et le remplissage.

La clé est d'utiliser CGSize titleSize = [myAnnotation.THETEXT sizeWithFont: [UIFont systemFontOfSize: 12]]; puis redéfinissez les dimensions de la vue. Vous pouvez appliquer cette logique à n'importe quelle vue, mais elle ne gère pas les sauts de ligne comme ceux de Pyjama.

Bien que la réponse de Pyjama fonctionne pour certains, cela n'a pas fonctionné pour moi. Ceci est une explication détaillée que vous devriez essayer immédiatement avant d'aller ailleurs si vous voulez une broche MKAnnotation personnalisée dynamique avec une image et UILabel redimensionnable.