163 votes

boundingRectWithSize pour NSAttributedString renvoyant une taille incorrecte

Je suis en train d'essayer d'obtenir le rect pour un attribué la chaîne, mais le boundingRectWithSize appel n'est pas en respectant la taille de la je passe en et est de retour à un rectangle avec une seule ligne de hauteur, par opposition à une grande hauteur (c'est une longue chaîne de caractères). J'ai expérimenté par le passage d'une très grande valeur pour la hauteur et aussi 0 comme dans le code ci-dessous, mais le rect retournée est toujours le même.

CGRect paragraphRect = [attributedText boundingRectWithSize:CGSizeMake(300,0.0)
  options:NSStringDrawingUsesDeviceMetrics
  context:nil];

Est-ce cassé, ou dois-je faire autre chose pour l'avoir retourné un rect pour le texte justifié?

328voto

Ed McManus Points 3024

On dirait que vous n'avez pas fourni les options correctes. Pour les étiquettes d'emballage, indiquez au moins:

 CGRect paragraphRect =
  [attributedText boundingRectWithSize:CGSizeMake(300.f, CGFLOAT_MAX)
  options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
  context:nil];
 

118voto

warrenm Points 10124

Cette méthode semble buggy dans de nombreuses façons. Pour l'un, comme vous le notez, il ne respecte pas la largeur de contraintes. D'autre part, je l'ai vu chuter, car il semble supposer que tous les attributs sont des NSObject type (par exemple, il a essayé de transmettre _isDefaultFace d'un CTFontRef). Il permettra également de crash parfois, quand une chaîne contexte de dessin est fourni parce qu'il essaie d'ajouter un néant valeur d'attribut à une mutable attribué chaîne de derrière les coulisses.

Je vous encourage à éviter cette méthode entièrement. Vous pouvez utiliser la Base de Texte directement pour estimer la taille de la chaîne, si vous pouvez gérer la surcharge de la création d'un framesetter pour chaque chaîne que vous avez besoin de dessiner. Il n'est pas, justement, l'honneur de la largeur de contraintes, mais il semble pour obtenir dans un délai de quelques pixels, dans mon expérience.

CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrString);
CGSize targetSize = CGSizeMake(320, CGFLOAT_MAX);
CGSize fitSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, [attrString length]), NULL, targetSize, NULL);
CFRelease(framesetter);

32voto

Paul Heller Points 531

Ed McManus a certainement donné une clé pour obtenir ce travail. J’ai trouvé un cas qui ne fonctionne pas

Rect n’aura pas la bonne hauteur. Notez anotherString (qui est ajoutée à la chaîne) a été initialisé sans un dictionnaire d’attribut. Il s’agit d’un initialiseur de légitime pour anotherString mais boundingRectWithSize : ne donne pas une taille précise, dans ce cas.

30voto

Ma décision finale après une longue enquête - boundingRectWithSize fonction renvoie la taille correcte pour une séquence ininterrompue de caractères seulement! Dans le cas de la chaîne contient des espaces ou quelque chose d'autre (appelé par Apple "des glyphes" ) - il est impossible d'obtenir la taille réelle de rect nécessaire à l'affichage de texte! J'ai remplacé les espaces dans mes cordes par des lettres et tout de suite eu un bon résultat.

Apple dit ici: https://developer.apple.com/library/ios/documentation/uikit/reference/NSString_UIKit_Additions/index.html#//apple_ref/occ/instm/NSString/boundingRectWithSize:options:attributes:context:

"Cette méthode retourne les réelles limites de la glyphes de la chaîne. Des glyphes (espaces, par exemple) sont autorisés à se chevauchent les contraintes de mise en forme spécifiée par la taille transmis, dans certains cas, la valeur de la largeur de la taille de la composante de l'retourné CGRect peut excéder la largeur de la valeur du paramètre taille."

Il est donc nécessaire de trouver un autre moyen de calculer l'effectif rect...

9voto

Roman B. Points 458

Si vous souhaitez obtenir une boîte englobante en tronquant la queue, cette question peut vous aider.

 CGFloat maxTitleWidth = 200;

NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.lineBreakMode = NSLineBreakByTruncatingTail;

NSDictionary *attributes = @{NSFontAttributeName : self.textLabel.font,
                             NSParagraphStyleAttributeName: paragraph};

CGRect box = [self.textLabel.text
              boundingRectWithSize:CGSizeMake(maxTitleWidth, CGFLOAT_MAX)
              options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
              attributes:attributes context:nil];
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X